Index: Dev/trunk/node_modules/grunt-contrib-watch/LICENSE-MIT
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/LICENSE-MIT	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/LICENSE-MIT	(revision 533)
@@ -0,0 +1,22 @@
+Copyright (c) 2014 "Cowboy" Ben Alman, contributors
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/README.md	(revision 533)
@@ -0,0 +1,486 @@
+# grunt-contrib-watch v0.6.1 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-watch.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-watch)
+
+> Run predefined tasks whenever watched file patterns are added, changed or deleted.
+
+
+
+## Getting Started
+This plugin requires Grunt `~0.4.0`
+
+If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
+
+```shell
+npm install grunt-contrib-watch --save-dev
+```
+
+Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
+
+```js
+grunt.loadNpmTasks('grunt-contrib-watch');
+```
+
+
+
+
+## Watch task
+_Run this task with the `grunt watch` command._
+
+
+### Settings
+
+There are a number of options available. Please review the [minimatch options here](https://github.com/isaacs/minimatch#options). As well as some additional options as follows:
+
+#### files
+Type: `String|Array`
+
+This defines what file patterns this task will watch. Can be a string or an array of files and/or minimatch patterns.
+
+#### tasks
+Type: `String|Array`
+
+This defines which tasks to run when a watched file event occurs.
+
+#### options.spawn
+Type: `Boolean`
+Default: true
+
+Whether to spawn task runs in a child process. Setting this option to `false` speeds up the reaction time of the watch (usually 500ms faster for most) and allows subsequent task runs to share the same context. Not spawning task runs can make the watch more prone to failing so please use as needed.
+
+Example:
+```js
+watch: {
+  scripts: {
+    files: ['**/*.js'],
+    tasks: ['jshint'],
+    options: {
+      spawn: false,
+    },
+  },
+},
+```
+
+*For backwards compatibility the option `nospawn` is still available and will do the opposite of `spawn`.*
+
+#### options.interrupt
+Type: `Boolean`
+Default: false
+
+As files are modified this watch task will spawn tasks in child processes. The default behavior will only spawn a new child process per target when the previous process has finished. Set the `interrupt` option to true to terminate the previous process and spawn a new one upon later changes.
+
+Example:
+```js
+watch: {
+  scripts: {
+    files: '**/*.js',
+    tasks: ['jshint'],
+    options: {
+      interrupt: true,
+    },
+  },
+},
+```
+
+#### options.debounceDelay
+Type: `Integer`
+Default: 500
+
+How long to wait before emitting events in succession for the same filepath and status. For example if your `Gruntfile.js` file was `changed`, a `changed` event will only fire again after the given milliseconds.
+
+Example:
+```js
+watch: {
+  scripts: {
+    files: '**/*.js',
+    tasks: ['jshint'],
+    options: {
+      debounceDelay: 250,
+    },
+  },
+},
+```
+
+#### options.interval
+Type: `Integer`
+Default: 100
+
+The `interval` is passed to `fs.watchFile`. Since `interval` is only used by `fs.watchFile` and this watcher also uses `fs.watch`; it is recommended to ignore this option. *Default is 100ms*.
+
+#### options.event
+Type: `String|Array`
+Default: `'all'`
+
+Specify the type watch event that trigger the specified task. This option can be one or many of: `'all'`, `'changed'`, `'added'` and `'deleted'`.
+
+Example:
+```js
+watch: {
+  scripts: {
+    files: '**/*.js',
+    tasks: ['generateFileManifest'],
+    options: {
+      event: ['added', 'deleted'],
+    },
+  },
+},
+```
+
+#### options.reload
+Type: `Boolean`
+Default: `false`
+
+By default, if `Gruntfile.js` is being watched, then changes to it will trigger the watch task to restart, and reload the `Gruntfile.js` changes.
+When `reload` is set to `true`, changes to *any* of the watched files will trigger the watch task to restart.
+This is especially useful if your `Gruntfile.js` is dependent on other files.
+
+```js
+watch: {
+  configFiles: {
+    files: [ 'Gruntfile.js', 'config/*.js' ],
+    options: {
+      reload: true
+    }
+  }
+}
+```
+
+
+#### options.forever
+Type: `Boolean`
+Default: true
+
+This is *only a task level option* and cannot be configured per target. By default the watch task will duck punch `grunt.fatal` and `grunt.warn` to try and prevent them from exiting the watch process. If you don't want `grunt.fatal` and `grunt.warn` to be overridden set the `forever` option to `false`.
+
+#### options.dateFormat
+Type: `Function`
+
+This is *only a task level option* and cannot be configured per target. By default when the watch has finished running tasks it will display the message `Completed in 1.301s at Thu Jul 18 2013 14:58:21 GMT-0700 (PDT) - Waiting...`. You can override this message by supplying your own function:
+
+```js
+watch: {
+  options: {
+    dateFormat: function(time) {
+      grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());
+      grunt.log.writeln('Waiting for more changes...');
+    },
+  },
+  scripts: {
+    files: '**/*.js',
+    tasks: 'jshint',
+  },
+},
+```
+
+#### options.atBegin
+Type: `Boolean`
+Default: false
+
+This option will trigger the run of each specified task at startup of the watcher.
+
+#### options.livereload
+Type: `Boolean|Number|Object`
+Default: false
+
+Set to `true` or set `livereload: 1337` to a port number to enable live reloading. Default and recommended port is `35729`.
+
+If enabled a live reload server will be started with the watch task per target. Then after the indicated tasks have ran, the live reload server will be triggered with the modified files.
+
+Example:
+```js
+watch: {
+  css: {
+    files: '**/*.sass',
+    tasks: ['sass'],
+    options: {
+      livereload: true,
+    },
+  },
+},
+```
+
+It's possible to get livereload working over https connections. To do this, pass an object to `livereload` with a `key` and `cert` paths specified.
+
+Example:
+```js
+watch: {
+  css: {
+    files: '**/*.sass',
+    tasks: ['sass'],
+    options: {
+      livereload: {
+        port: 9000,
+        key: grunt.file.read('path/to/ssl.key'),
+        cert: grunt.file.read('path/to/ssl.crt')
+        // you can pass in any other options you'd like to the https server, as listed here: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
+      }
+    },
+  },
+},
+```
+
+
+#### options.cwd
+Type: `String|Object`
+Default: `process.cwd()`
+
+Ability to set the current working directory. Defaults to `process.cwd()`. Can either be a string to set the cwd to match files and spawn tasks. Or an object to set each independently. Such as `options: { cwd: { files: 'match/files/from/here', spawn: 'but/spawn/files/from/here' } }`.
+
+#### options.livereloadOnError
+Type: `Boolean`  
+Default: `true`  
+
+Option to prevent the livereload if the executed tasks encountered an error.  If set to `false`, the livereload will only be triggered if all tasks completed successfully.
+
+### Examples
+
+```js
+// Simple config to run jshint any time a file is added, changed or deleted
+grunt.initConfig({
+  watch: {
+    files: ['**/*'],
+    tasks: ['jshint'],
+  },
+});
+```
+
+```js
+// Advanced config. Run specific tasks when specific files are added, changed or deleted.
+grunt.initConfig({
+  watch: {
+    gruntfile: {
+      files: 'Gruntfile.js',
+      tasks: ['jshint:gruntfile'],
+    },
+    src: {
+      files: ['lib/*.js', 'css/**/*.scss', '!lib/dontwatch.js'],
+      tasks: ['default'],
+    },
+    test: {
+      files: '<%= jshint.test.src %>',
+      tasks: ['jshint:test', 'qunit'],
+    },
+  },
+});
+```
+
+#### Using the `watch` event
+This task will emit a `watch` event when watched files are modified. This is useful if you would like a simple notification when files are edited or if you're using this task in tandem with another task. Here is a simple example using the `watch` event:
+
+```js
+grunt.initConfig({
+  watch: {
+    scripts: {
+      files: ['lib/*.js'],
+    },
+  },
+});
+grunt.event.on('watch', function(action, filepath, target) {
+  grunt.log.writeln(target + ': ' + filepath + ' has ' + action);
+});
+```
+
+**The `watch` event is not intended for replacing the standard Grunt API for configuring and running tasks. If you're trying to run tasks from within the `watch` event you're more than likely doing it wrong. Please read [configuring tasks](http://gruntjs.com/configuring-tasks).**
+
+##### Compiling Files As Needed
+A very common request is to only compile files as needed. Here is an example that will only lint changed files with the `jshint` task:
+
+```js
+grunt.initConfig({
+  watch: {
+    scripts: {
+      files: ['lib/*.js'],
+      tasks: ['jshint'],
+      options: {
+        spawn: false,
+      },
+    },
+  },
+  jshint: {
+    all: {
+      src: ['lib/*.js'],
+    },
+  },
+});
+
+// on watch events configure jshint:all to only run on changed file
+grunt.event.on('watch', function(action, filepath) {
+  grunt.config('jshint.all.src', filepath);
+});
+```
+
+If you need to dynamically modify your config, the `spawn` option must be disabled to keep the watch running under the same context.
+
+If you save multiple files simultaneously you may opt for a more robust method:
+
+```js
+var changedFiles = Object.create(null);
+var onChange = grunt.util._.debounce(function() {
+  grunt.config('jshint.all.src', Object.keys(changedFiles));
+  changedFiles = Object.create(null);
+}, 200);
+grunt.event.on('watch', function(action, filepath) {
+  changedFiles[filepath] = action;
+  onChange();
+});
+```
+
+#### Live Reloading
+Live reloading is built into the watch task. Set the option `livereload` to `true` to enable on the default port `35729` or set to a custom port: `livereload: 1337`.
+
+The simplest way to add live reloading to all your watch targets is by setting `livereload` to `true` at the task level. This will run a single live reload server and trigger the live reload for all your watch targets:
+
+```js
+grunt.initConfig({
+  watch: {
+    options: {
+      livereload: true,
+    },
+    css: {
+      files: ['public/scss/*.scss'],
+      tasks: ['compass'],
+    },
+  },
+});
+```
+
+You can also configure live reload for individual watch targets or run multiple live reload servers. Just be sure if you're starting multiple servers they operate on different ports:
+
+```js
+grunt.initConfig({
+  watch: {
+    css: {
+      files: ['public/scss/*.scss'],
+      tasks: ['compass'],
+      options: {
+        // Start a live reload server on the default port 35729
+        livereload: true,
+      },
+    },
+    another: {
+      files: ['lib/*.js'],
+      tasks: ['anothertask'],
+      options: {
+        // Start another live reload server on port 1337
+        livereload: 1337,
+      },
+    },
+    dont: {
+      files: ['other/stuff/*'],
+      tasks: ['dostuff'],
+    },
+  },
+});
+```
+
+##### Enabling Live Reload in Your HTML
+Once you've started a live reload server you'll be able to access the live reload script. To enable live reload on your page, add a script tag before your closing `</body>` tag pointing to the `livereload.js` script:
+
+```html
+<script src="//localhost:35729/livereload.js"></script>
+```
+
+Feel free to add this script to your template situation and toggle with some sort of `dev` flag.
+
+##### Using Live Reload with the Browser Extension
+Instead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser.
+
+Once installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the `<script>` tag.
+
+##### Using Connect Middleware
+Since live reloading is used when developing, you may want to disable building for production (and are not using the browser extension). One method is to use Connect middleware to inject the script tag into your page. Try the [connect-livereload](https://github.com/intesso/connect-livereload) middleware for injecting the live reload script into your page.
+
+##### Rolling Your Own Live Reload
+Live reloading is made easy by the library [tiny-lr](https://github.com/mklabs/tiny-lr). It is encouraged to read the documentation for `tiny-lr`. If you would like to trigger the live reload server yourself, simply POST files to the URL: `http://localhost:35729/changed`. Or if you rather roll your own live reload implementation use the following example:
+
+```js
+// Create a live reload server instance
+var lrserver = require('tiny-lr')();
+
+// Listen on port 35729
+lrserver.listen(35729, function(err) { console.log('LR Server Started'); });
+
+// Then later trigger files or POST to localhost:35729/changed
+lrserver.changed({body:{files:['public/css/changed.css']}});
+```
+
+##### Live Reload with Preprocessors
+Any time a watched file is edited with the `livereload` option enabled, the file will be sent to the live reload server. Some edited files you may desire to have sent to the live reload server, such as when preprocessing (`sass`, `less`, `coffeescript`, etc). As any file not recognized will reload the entire page as opposed to just the `css` or `javascript`.
+
+The solution is to point a `livereload` watch target to your destination files:
+
+```js
+grunt.initConfig({
+  sass: {
+    dev: {
+      src: ['src/sass/*.sass'],
+      dest: 'dest/css/index.css',
+    },
+  },
+  watch: {
+    sass: {
+      // We watch and compile sass files as normal but don't live reload here
+      files: ['src/sass/*.sass'],
+      tasks: ['sass'],
+    },
+    livereload: {
+      // Here we watch the files the sass task will compile to
+      // These files are sent to the live reload server after sass compiles to them
+      options: { livereload: true },
+      files: ['dest/**/*'],
+    },
+  },
+});
+```
+
+### FAQs
+
+#### How do I fix the error `EMFILE: Too many opened files.`?
+This is because of your system's max opened file limit. For OSX the default is very low (256). Temporarily increase your limit with `ulimit -n 10480`, the number being the new max limit.
+
+In some versions of OSX the above solution doesn't work. In that case try `launchctl limit maxfiles 10480 10480 ` and restart your terminal. See [here](http://superuser.com/questions/261023/how-to-change-default-ulimit-values-in-mac-os-x-10-6).
+
+#### Can I use this with Grunt v0.3?
+`grunt-contrib-watch@0.1.x` is compatible with Grunt v0.3 but it is highly recommended to upgrade Grunt instead.
+
+#### Why is the watch devouring all my memory/cpu?
+Likely because of an enthusiastic pattern trying to watch thousands of files. Such as `'**/*.js'` but forgetting to exclude the `node_modules` folder with `'!**/node_modules/**'`. Try grouping your files within a subfolder or be more explicit with your file matching pattern.
+
+Another reason if you're watching a large number of files could be the low default `interval`. Try increasing with `options: { interval: 5007 }`. Please see issues [#35](https://github.com/gruntjs/grunt-contrib-watch/issues/145) and [#145](https://github.com/gruntjs/grunt-contrib-watch/issues/145) for more information.
+
+#### Why spawn as child processes as a default?
+The goal of this watch task is as files are changed, run tasks as if they were triggered by the user themself. Each time a user runs `grunt` a process is spawned and tasks are ran in succession. In an effort to keep the experience consistent and continually produce expected results, this watch task spawns tasks as child processes by default.
+
+Sandboxing task runs also allows this watch task to run more stable over long periods of time. As well as more efficiently with more complex tasks and file structures.
+
+Spawning does cause a performance hit (usually 500ms for most environments). It also cripples tasks that rely on the watch task to share the context with each subsequent run (i.e., reload tasks). If you would like a faster watch task or need to share the context please set the `spawn` option to `false`. Just be aware that with this option enabled, the watch task is more prone to failure.
+
+
+## Release History
+
+ * 2014-03-19âââv0.6.1âââFix for watch targets named "default"
+ * 2014-03-11âââv0.6.0âââClear changed files after triggering live reload to ensure they're only triggered once. cwd option now accepts separate settings for files and spawn. Fix to make interrupt work more than once. Enable live reload over HTTPS. Print newline after initial 'Waiting...' Remove deprecated grunt.util libs Add reload option to specify files other than Gruntfile files to reload. Update to gaze@0.5.1 Use fork of tiny-lr (which has quiter operation, support for HTTPS and windows path fixes) Add livereloadOnError, which if set to false will not trigger live reload if there is an error.
+ * 2013-08-25âââv0.5.3âââFixed for live reload missing files.
+ * 2013-08-16âââv0.5.2âââFixed issue running tasks after gruntfile is reloaded. Ignores empty file paths.
+ * 2013-07-20âââv0.5.1âââFixed issue with options resetting.
+ * 2013-07-18âââv0.5.0âââAdded target name to watch event. Added atBegin option to run tasks when watcher starts. Changed nospawn option to spawn (nospawn still available for backwards compatibility). Moved libs/vars into top scope to prevent re-init. Bumped Gaze version to ~0.4. Re-grab task/target options upon each task run. Add dateFormat option to override the date/time output upon completion.
+ * 2013-05-27âââv0.4.4âââRemove gracefully closing SIGINT. Not needed and causes problems for Windows. Ensure tasks are an array to not conflict with cliArgs.
+ * 2013-05-11âââv0.4.3âââOnly group changed files per target to send correct files to live reload.
+ * 2013-05-09âââv0.4.2âââFix for closing watchers.
+ * 2013-05-09âââv0.4.1âââRemoved "beep" notification. Tasks now optional with livereload option. Reverted "run again" with interrupt off to fix infinite recursion issue. Watchers now close more properly on task run.
+ * 2013-05-03âââv0.4.0âââOption livereload to start live reload servers. Will reload a Gruntfile before running tasks if Gruntfile is modified. Option event to only trigger watch on certain events. Refactor watch task into separate task runs per target. Option forever to override grunt.fatal/warn to help keeping the watch alive with nospawn enabled. Emit a beep upon complete. Logs all watched files with verbose flag set. If interrupt is off, will run the tasks once more if watch triggered during a previous task run. tasks property is optional for use with watch event. Watchers properly closed when exiting.
+ * 2013-02-28âââv0.3.1âââFix for top level options.
+ * 2013-02-27âââv0.3.0ââânospawn option added to run tasks without spawning as child processes. Watch emits 'watch' events upon files being triggered with grunt.event. Completion time in seconds and date/time shown after tasks ran. Negate file patterns fixed. Tasks debounced individually to handle simultaneous triggering for multiple targets. Errors handled better and viewable with --stack cli option. Code complexity reduced making the watch task code easier to read.
+ * 2013-02-15âââv0.2.0âââFirst official release for Grunt 0.4.0.
+ * 2013-01-18âââv0.2.0rc7âââUpdating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.
+ * 2013-01-09âââv0.2.0rc5âââUpdating to work with grunt v0.4.0rc5.
+ * 2012-12-15âââv0.2.0aâââConversion to grunt v0.4 conventions. Remove node v0.6 and grunt v0.3 support. Allow watch task to be renamed. Use grunt.util.spawn "grunt" option. Updated to gaze@0.3.0, forceWatchMethod option removed.
+ * 2012-11-01âââv0.1.4âââPrevent watch from spawning duplicate watch tasks
+ * 2012-10-28âââv0.1.3âââBetter method to spawn the grunt bin Bump gaze to v0.2.0. Better handles some events and new option forceWatchMethod Only support Node.js >= v0.8
+ * 2012-10-17âââv0.1.2âââOnly spawn a process per task one at a time Add interrupt option to cancel previous spawned process Grunt v0.3 compatibility changes
+ * 2012-10-16âââv0.1.1âââFallback to global grunt bin if local doesnt exist. Fatal if bin cannot be found Update to gaze 0.1.6
+ * 2012-10-08âââv0.1.0âââRelease watch task Remove spawn from helper Run on Grunt v0.4
+
+---
+
+Task submitted by [Kyle Robinson Young](http://dontkry.com)
+
+*This file was generated on Wed Mar 19 2014 13:09:11.*
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/.bin/tiny-lr-fork
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/.bin/tiny-lr-fork	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/.bin/tiny-lr-fork	(revision 533)
@@ -0,0 +1,1 @@
+link ../tiny-lr-fork/bin/tiny-lr
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/LICENSE	(revision 533)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Caolan McMahon
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/README.md	(revision 533)
@@ -0,0 +1,1425 @@
+# Async.js
+
+Async is a utility module which provides straight-forward, powerful functions
+for working with asynchronous JavaScript. Although originally designed for
+use with [node.js](http://nodejs.org), it can also be used directly in the
+browser. Also supports [component](https://github.com/component/component).
+
+Async provides around 20 functions that include the usual 'functional'
+suspects (map, reduce, filter, eachâŠ) as well as some common patterns
+for asynchronous control flow (parallel, series, waterfallâŠ). All these
+functions assume you follow the node.js convention of providing a single
+callback as the last argument of your async function.
+
+
+## Quick Examples
+
+```javascript
+async.map(['file1','file2','file3'], fs.stat, function(err, results){
+    // results is now an array of stats for each file
+});
+
+async.filter(['file1','file2','file3'], fs.exists, function(results){
+    // results now equals an array of the existing files
+});
+
+async.parallel([
+    function(){ ... },
+    function(){ ... }
+], callback);
+
+async.series([
+    function(){ ... },
+    function(){ ... }
+]);
+```
+
+There are many more functions available so take a look at the docs below for a
+full list. This module aims to be comprehensive, so if you feel anything is
+missing please create a GitHub issue for it.
+
+## Common Pitfalls
+
+### Binding a context to an iterator
+
+This section is really about bind, not about async. If you are wondering how to
+make async execute your iterators in a given context, or are confused as to why
+a method of another library isn't working as an iterator, study this example:
+
+```js
+// Here is a simple object with an (unnecessarily roundabout) squaring method
+var AsyncSquaringLibrary = {
+  squareExponent: 2,
+  square: function(number, callback){ 
+    var result = Math.pow(number, this.squareExponent);
+    setTimeout(function(){
+      callback(null, result);
+    }, 200);
+  }
+};
+
+async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){
+  // result is [NaN, NaN, NaN]
+  // This fails because the `this.squareExponent` expression in the square
+  // function is not evaluated in the context of AsyncSquaringLibrary, and is
+  // therefore undefined.
+});
+
+async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){
+  // result is [1, 4, 9]
+  // With the help of bind we can attach a context to the iterator before
+  // passing it to async. Now the square function will be executed in its 
+  // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`
+  // will be as expected.
+});
+```
+
+## Download
+
+The source is available for download from
+[GitHub](http://github.com/caolan/async).
+Alternatively, you can install using Node Package Manager (npm):
+
+    npm install async
+
+__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed
+
+## In the Browser
+
+So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
+
+```html
+<script type="text/javascript" src="async.js"></script>
+<script type="text/javascript">
+
+    async.map(data, asyncProcess, function(err, results){
+        alert(results);
+    });
+
+</script>
+```
+
+## Documentation
+
+### Collections
+
+* [each](#each)
+* [eachSeries](#eachSeries)
+* [eachLimit](#eachLimit)
+* [map](#map)
+* [mapSeries](#mapSeries)
+* [mapLimit](#mapLimit)
+* [filter](#filter)
+* [filterSeries](#filterSeries)
+* [reject](#reject)
+* [rejectSeries](#rejectSeries)
+* [reduce](#reduce)
+* [reduceRight](#reduceRight)
+* [detect](#detect)
+* [detectSeries](#detectSeries)
+* [sortBy](#sortBy)
+* [some](#some)
+* [every](#every)
+* [concat](#concat)
+* [concatSeries](#concatSeries)
+
+### Control Flow
+
+* [series](#series)
+* [parallel](#parallel)
+* [parallelLimit](#parallellimittasks-limit-callback)
+* [whilst](#whilst)
+* [doWhilst](#doWhilst)
+* [until](#until)
+* [doUntil](#doUntil)
+* [forever](#forever)
+* [waterfall](#waterfall)
+* [compose](#compose)
+* [applyEach](#applyEach)
+* [applyEachSeries](#applyEachSeries)
+* [queue](#queue)
+* [cargo](#cargo)
+* [auto](#auto)
+* [iterator](#iterator)
+* [apply](#apply)
+* [nextTick](#nextTick)
+* [times](#times)
+* [timesSeries](#timesSeries)
+
+### Utils
+
+* [memoize](#memoize)
+* [unmemoize](#unmemoize)
+* [log](#log)
+* [dir](#dir)
+* [noConflict](#noConflict)
+
+
+## Collections
+
+<a name="forEach" />
+<a name="each" />
+### each(arr, iterator, callback)
+
+Applies an iterator function to each item in an array, in parallel.
+The iterator is called with an item from the list and a callback for when it
+has finished. If the iterator passes an error to this callback, the main
+callback for the each function is immediately called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err) which must be called once it has 
+  completed. If no error has occured, the callback should be run without 
+  arguments or with an explicit null argument.
+* callback(err) - A callback which is called after all the iterator functions
+  have finished, or an error has occurred.
+
+__Example__
+
+```js
+// assuming openFiles is an array of file names and saveFile is a function
+// to save the modified contents of that file:
+
+async.each(openFiles, saveFile, function(err){
+    // if any of the saves produced an error, err would equal that error
+});
+```
+
+---------------------------------------
+
+<a name="forEachSeries" />
+<a name="eachSeries" />
+### eachSeries(arr, iterator, callback)
+
+The same as each only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. This means the iterator functions will complete in order.
+
+
+---------------------------------------
+
+<a name="forEachLimit" />
+<a name="eachLimit" />
+### eachLimit(arr, limit, iterator, callback)
+
+The same as each only no more than "limit" iterators will be simultaneously 
+running at any time.
+
+Note that the items are not processed in batches, so there is no guarantee that
+ the first "limit" iterator functions will complete before any others are 
+started.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - The maximum number of iterators to run at any time.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err) which must be called once it has 
+  completed. If no error has occured, the callback should be run without 
+  arguments or with an explicit null argument.
+* callback(err) - A callback which is called after all the iterator functions
+  have finished, or an error has occurred.
+
+__Example__
+
+```js
+// Assume documents is an array of JSON objects and requestApi is a
+// function that interacts with a rate-limited REST api.
+
+async.eachLimit(documents, 20, requestApi, function(err){
+    // if any of the saves produced an error, err would equal that error
+});
+```
+
+---------------------------------------
+
+<a name="map" />
+### map(arr, iterator, callback)
+
+Produces a new array of values by mapping each value in the given array through
+the iterator function. The iterator is called with an item from the array and a
+callback for when it has finished processing. The callback takes 2 arguments, 
+an error and the transformed item from the array. If the iterator passes an
+error to this callback, the main callback for the map function is immediately
+called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order, however
+the results array will be in the same order as the original array.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, transformed) which must be called once 
+  it has completed with an error (which can be null) and a transformed item.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is an array of the
+  transformed items from the original array.
+
+__Example__
+
+```js
+async.map(['file1','file2','file3'], fs.stat, function(err, results){
+    // results is now an array of stats for each file
+});
+```
+
+---------------------------------------
+
+<a name="mapSeries" />
+### mapSeries(arr, iterator, callback)
+
+The same as map only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+
+---------------------------------------
+
+<a name="mapLimit" />
+### mapLimit(arr, limit, iterator, callback)
+
+The same as map only no more than "limit" iterators will be simultaneously 
+running at any time.
+
+Note that the items are not processed in batches, so there is no guarantee that
+ the first "limit" iterator functions will complete before any others are 
+started.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - The maximum number of iterators to run at any time.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, transformed) which must be called once 
+  it has completed with an error (which can be null) and a transformed item.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is an array of the
+  transformed items from the original array.
+
+__Example__
+
+```js
+async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){
+    // results is now an array of stats for each file
+});
+```
+
+---------------------------------------
+
+<a name="filter" />
+### filter(arr, iterator, callback)
+
+__Alias:__ select
+
+Returns a new array of all the values which pass an async truth test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like fs.exists. This operation is
+performed in parallel, but the results array will be in the same order as the
+original.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(results) - A callback which is called after all the iterator
+  functions have finished.
+
+__Example__
+
+```js
+async.filter(['file1','file2','file3'], fs.exists, function(results){
+    // results now equals an array of the existing files
+});
+```
+
+---------------------------------------
+
+<a name="filterSeries" />
+### filterSeries(arr, iterator, callback)
+
+__alias:__ selectSeries
+
+The same as filter only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+---------------------------------------
+
+<a name="reject" />
+### reject(arr, iterator, callback)
+
+The opposite of filter. Removes values that pass an async truth test.
+
+---------------------------------------
+
+<a name="rejectSeries" />
+### rejectSeries(arr, iterator, callback)
+
+The same as reject, only the iterator is applied to each item in the array
+in series.
+
+
+---------------------------------------
+
+<a name="reduce" />
+### reduce(arr, memo, iterator, callback)
+
+__aliases:__ inject, foldl
+
+Reduces a list of values into a single value using an async iterator to return
+each successive step. Memo is the initial state of the reduction. This
+function only operates in series. For performance reasons, it may make sense to
+split a call to this function into a parallel map, then use the normal
+Array.prototype.reduce on the results. This function is for situations where
+each step in the reduction needs to be async, if you can get the data before
+reducing it then it's probably a good idea to do so.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* memo - The initial state of the reduction.
+* iterator(memo, item, callback) - A function applied to each item in the
+  array to produce the next step in the reduction. The iterator is passed a
+  callback(err, reduction) which accepts an optional error as its first 
+  argument, and the state of the reduction as the second. If an error is 
+  passed to the callback, the reduction is stopped and the main callback is 
+  immediately called with the error.
+* callback(err, result) - A callback which is called after all the iterator
+  functions have finished. Result is the reduced value.
+
+__Example__
+
+```js
+async.reduce([1,2,3], 0, function(memo, item, callback){
+    // pointless async:
+    process.nextTick(function(){
+        callback(null, memo + item)
+    });
+}, function(err, result){
+    // result is now equal to the last value of memo, which is 6
+});
+```
+
+---------------------------------------
+
+<a name="reduceRight" />
+### reduceRight(arr, memo, iterator, callback)
+
+__Alias:__ foldr
+
+Same as reduce, only operates on the items in the array in reverse order.
+
+
+---------------------------------------
+
+<a name="detect" />
+### detect(arr, iterator, callback)
+
+Returns the first value in a list that passes an async truth test. The
+iterator is applied in parallel, meaning the first iterator to return true will
+fire the detect callback with that result. That means the result might not be
+the first item in the original array (in terms of order) that passes the test.
+
+If order within the original array is important then look at detectSeries.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+  true, or after all the iterator functions have finished. Result will be
+  the first item in the array that passes the truth test (iterator) or the
+  value undefined if none passed.
+
+__Example__
+
+```js
+async.detect(['file1','file2','file3'], fs.exists, function(result){
+    // result now equals the first file in the list that exists
+});
+```
+
+---------------------------------------
+
+<a name="detectSeries" />
+### detectSeries(arr, iterator, callback)
+
+The same as detect, only the iterator is applied to each item in the array
+in series. This means the result is always the first in the original array (in
+terms of array order) that passes the truth test.
+
+
+---------------------------------------
+
+<a name="sortBy" />
+### sortBy(arr, iterator, callback)
+
+Sorts a list by the results of running each value through an async iterator.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, sortValue) which must be called once it
+  has completed with an error (which can be null) and a value to use as the sort
+  criteria.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is the items from
+  the original array sorted by the values returned by the iterator calls.
+
+__Example__
+
+```js
+async.sortBy(['file1','file2','file3'], function(file, callback){
+    fs.stat(file, function(err, stats){
+        callback(err, stats.mtime);
+    });
+}, function(err, results){
+    // results is now the original array of files sorted by
+    // modified date
+});
+```
+
+---------------------------------------
+
+<a name="some" />
+### some(arr, iterator, callback)
+
+__Alias:__ any
+
+Returns true if at least one element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like fs.exists. Once any iterator
+call returns true, the main callback is immediately called.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+  true, or after all the iterator functions have finished. Result will be
+  either true or false depending on the values of the async tests.
+
+__Example__
+
+```js
+async.some(['file1','file2','file3'], fs.exists, function(result){
+    // if result is true then at least one of the files exists
+});
+```
+
+---------------------------------------
+
+<a name="every" />
+### every(arr, iterator, callback)
+
+__Alias:__ all
+
+Returns true if every element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like fs.exists.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(result) - A callback which is called after all the iterator
+  functions have finished. Result will be either true or false depending on
+  the values of the async tests.
+
+__Example__
+
+```js
+async.every(['file1','file2','file3'], fs.exists, function(result){
+    // if result is true then every file exists
+});
+```
+
+---------------------------------------
+
+<a name="concat" />
+### concat(arr, iterator, callback)
+
+Applies an iterator to each item in a list, concatenating the results. Returns the
+concatenated list. The iterators are called in parallel, and the results are
+concatenated as they return. There is no guarantee that the results array will
+be returned in the original order of the arguments passed to the iterator function.
+
+__Arguments__
+
+* arr - An array to iterate over
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, results) which must be called once it 
+  has completed with an error (which can be null) and an array of results.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is an array containing
+  the concatenated results of the iterator function.
+
+__Example__
+
+```js
+async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
+    // files is now a list of filenames that exist in the 3 directories
+});
+```
+
+---------------------------------------
+
+<a name="concatSeries" />
+### concatSeries(arr, iterator, callback)
+
+Same as async.concat, but executes in series instead of parallel.
+
+
+## Control Flow
+
+<a name="series" />
+### series(tasks, [callback])
+
+Run an array of functions in series, each one running once the previous
+function has completed. If any functions in the series pass an error to its
+callback, no more functions are run and the callback for the series is
+immediately called with the value of the error. Once the tasks have completed,
+the results are passed to the final callback as an array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.series.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed
+  a callback(err, result) it must call on completion with an error (which can
+  be null) and an optional result value.
+* callback(err, results) - An optional callback to run once all the functions
+  have completed. This function gets a results array (or object) containing all 
+  the result arguments passed to the task callbacks.
+
+__Example__
+
+```js
+async.series([
+    function(callback){
+        // do some stuff ...
+        callback(null, 'one');
+    },
+    function(callback){
+        // do some more stuff ...
+        callback(null, 'two');
+    }
+],
+// optional callback
+function(err, results){
+    // results is now equal to ['one', 'two']
+});
+
+
+// an example using an object instead of an array
+async.series({
+    one: function(callback){
+        setTimeout(function(){
+            callback(null, 1);
+        }, 200);
+    },
+    two: function(callback){
+        setTimeout(function(){
+            callback(null, 2);
+        }, 100);
+    }
+},
+function(err, results) {
+    // results is now equal to: {one: 1, two: 2}
+});
+```
+
+---------------------------------------
+
+<a name="parallel" />
+### parallel(tasks, [callback])
+
+Run an array of functions in parallel, without waiting until the previous
+function has completed. If any of the functions pass an error to its
+callback, the main callback is immediately called with the value of the error.
+Once the tasks have completed, the results are passed to the final callback as an
+array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.parallel.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed 
+  a callback(err, result) it must call on completion with an error (which can
+  be null) and an optional result value.
+* callback(err, results) - An optional callback to run once all the functions
+  have completed. This function gets a results array (or object) containing all 
+  the result arguments passed to the task callbacks.
+
+__Example__
+
+```js
+async.parallel([
+    function(callback){
+        setTimeout(function(){
+            callback(null, 'one');
+        }, 200);
+    },
+    function(callback){
+        setTimeout(function(){
+            callback(null, 'two');
+        }, 100);
+    }
+],
+// optional callback
+function(err, results){
+    // the results array will equal ['one','two'] even though
+    // the second function had a shorter timeout.
+});
+
+
+// an example using an object instead of an array
+async.parallel({
+    one: function(callback){
+        setTimeout(function(){
+            callback(null, 1);
+        }, 200);
+    },
+    two: function(callback){
+        setTimeout(function(){
+            callback(null, 2);
+        }, 100);
+    }
+},
+function(err, results) {
+    // results is now equals to: {one: 1, two: 2}
+});
+```
+
+---------------------------------------
+
+<a name="parallel" />
+### parallelLimit(tasks, limit, [callback])
+
+The same as parallel only the tasks are executed in parallel with a maximum of "limit" 
+tasks executing at any time.
+
+Note that the tasks are not executed in batches, so there is no guarantee that 
+the first "limit" tasks will complete before any others are started.
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed 
+  a callback(err, result) it must call on completion with an error (which can
+  be null) and an optional result value.
+* limit - The maximum number of tasks to run at any time.
+* callback(err, results) - An optional callback to run once all the functions
+  have completed. This function gets a results array (or object) containing all 
+  the result arguments passed to the task callbacks.
+
+---------------------------------------
+
+<a name="whilst" />
+### whilst(test, fn, callback)
+
+Repeatedly call fn, while test returns true. Calls the callback when stopped,
+or an error occurs.
+
+__Arguments__
+
+* test() - synchronous truth test to perform before each execution of fn.
+* fn(callback) - A function to call each time the test passes. The function is
+  passed a callback(err) which must be called once it has completed with an 
+  optional error argument.
+* callback(err) - A callback which is called after the test fails and repeated
+  execution of fn has stopped.
+
+__Example__
+
+```js
+var count = 0;
+
+async.whilst(
+    function () { return count < 5; },
+    function (callback) {
+        count++;
+        setTimeout(callback, 1000);
+    },
+    function (err) {
+        // 5 seconds have passed
+    }
+);
+```
+
+---------------------------------------
+
+<a name="doWhilst" />
+### doWhilst(fn, test, callback)
+
+The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
+
+---------------------------------------
+
+<a name="until" />
+### until(test, fn, callback)
+
+Repeatedly call fn, until test returns true. Calls the callback when stopped,
+or an error occurs.
+
+The inverse of async.whilst.
+
+---------------------------------------
+
+<a name="doUntil" />
+### doUntil(fn, test, callback)
+
+Like doWhilst except the test is inverted. Note the argument ordering differs from `until`.
+
+---------------------------------------
+
+<a name="forever" />
+### forever(fn, callback)
+
+Calls the asynchronous function 'fn' repeatedly, in series, indefinitely.
+If an error is passed to fn's callback then 'callback' is called with the
+error, otherwise it will never be called.
+
+---------------------------------------
+
+<a name="waterfall" />
+### waterfall(tasks, [callback])
+
+Runs an array of functions in series, each passing their results to the next in
+the array. However, if any of the functions pass an error to the callback, the
+next function is not executed and the main callback is immediately called with
+the error.
+
+__Arguments__
+
+* tasks - An array of functions to run, each function is passed a 
+  callback(err, result1, result2, ...) it must call on completion. The first
+  argument is an error (which can be null) and any further arguments will be 
+  passed as arguments in order to the next task.
+* callback(err, [results]) - An optional callback to run once all the functions
+  have completed. This will be passed the results of the last task's callback.
+
+
+
+__Example__
+
+```js
+async.waterfall([
+    function(callback){
+        callback(null, 'one', 'two');
+    },
+    function(arg1, arg2, callback){
+        callback(null, 'three');
+    },
+    function(arg1, callback){
+        // arg1 now equals 'three'
+        callback(null, 'done');
+    }
+], function (err, result) {
+   // result now equals 'done'    
+});
+```
+
+---------------------------------------
+<a name="compose" />
+### compose(fn1, fn2...)
+
+Creates a function which is a composition of the passed asynchronous
+functions. Each function consumes the return value of the function that
+follows. Composing functions f(), g() and h() would produce the result of
+f(g(h())), only this version uses callbacks to obtain the return values.
+
+Each function is executed with the `this` binding of the composed function.
+
+__Arguments__
+
+* functions... - the asynchronous functions to compose
+
+
+__Example__
+
+```js
+function add1(n, callback) {
+    setTimeout(function () {
+        callback(null, n + 1);
+    }, 10);
+}
+
+function mul3(n, callback) {
+    setTimeout(function () {
+        callback(null, n * 3);
+    }, 10);
+}
+
+var add1mul3 = async.compose(mul3, add1);
+
+add1mul3(4, function (err, result) {
+   // result now equals 15
+});
+```
+
+---------------------------------------
+<a name="applyEach" />
+### applyEach(fns, args..., callback)
+
+Applies the provided arguments to each function in the array, calling the
+callback after all functions have completed. If you only provide the first
+argument then it will return a function which lets you pass in the
+arguments as if it were a single function call.
+
+__Arguments__
+
+* fns - the asynchronous functions to all call with the same arguments
+* args... - any number of separate arguments to pass to the function
+* callback - the final argument should be the callback, called when all
+  functions have completed processing
+
+
+__Example__
+
+```js
+async.applyEach([enableSearch, updateSchema], 'bucket', callback);
+
+// partial application example:
+async.each(
+    buckets,
+    async.applyEach([enableSearch, updateSchema]),
+    callback
+);
+```
+
+---------------------------------------
+
+<a name="applyEachSeries" />
+### applyEachSeries(arr, iterator, callback)
+
+The same as applyEach only the functions are applied in series.
+
+---------------------------------------
+
+<a name="queue" />
+### queue(worker, concurrency)
+
+Creates a queue object with the specified concurrency. Tasks added to the
+queue will be processed in parallel (up to the concurrency limit). If all
+workers are in progress, the task is queued until one is available. Once
+a worker has completed a task, the task's callback is called.
+
+__Arguments__
+
+* worker(task, callback) - An asynchronous function for processing a queued
+  task, which must call its callback(err) argument when finished, with an 
+  optional error as an argument.
+* concurrency - An integer for determining how many worker functions should be
+  run in parallel.
+
+__Queue objects__
+
+The queue object returned by this function has the following properties and
+methods:
+
+* length() - a function returning the number of items waiting to be processed.
+* concurrency - an integer for determining how many worker functions should be
+  run in parallel. This property can be changed after a queue is created to
+  alter the concurrency on-the-fly.
+* push(task, [callback]) - add a new task to the queue, the callback is called
+  once the worker has finished processing the task.
+  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
+* unshift(task, [callback]) - add a new task to the front of the queue.
+* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
+* empty - a callback that is called when the last item from the queue is given to a worker
+* drain - a callback that is called when the last item from the queue has returned from the worker
+
+__Example__
+
+```js
+// create a queue object with concurrency 2
+
+var q = async.queue(function (task, callback) {
+    console.log('hello ' + task.name);
+    callback();
+}, 2);
+
+
+// assign a callback
+q.drain = function() {
+    console.log('all items have been processed');
+}
+
+// add some items to the queue
+
+q.push({name: 'foo'}, function (err) {
+    console.log('finished processing foo');
+});
+q.push({name: 'bar'}, function (err) {
+    console.log('finished processing bar');
+});
+
+// add some items to the queue (batch-wise)
+
+q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
+    console.log('finished processing bar');
+});
+
+// add some items to the front of the queue
+
+q.unshift({name: 'bar'}, function (err) {
+    console.log('finished processing bar');
+});
+```
+
+---------------------------------------
+
+<a name="cargo" />
+### cargo(worker, [payload])
+
+Creates a cargo object with the specified payload. Tasks added to the
+cargo will be processed altogether (up to the payload limit). If the
+worker is in progress, the task is queued until it is available. Once
+the worker has completed some tasks, each callback of those tasks is called.
+
+__Arguments__
+
+* worker(tasks, callback) - An asynchronous function for processing an array of
+  queued tasks, which must call its callback(err) argument when finished, with 
+  an optional error as an argument.
+* payload - An optional integer for determining how many tasks should be
+  processed per round; if omitted, the default is unlimited.
+
+__Cargo objects__
+
+The cargo object returned by this function has the following properties and
+methods:
+
+* length() - a function returning the number of items waiting to be processed.
+* payload - an integer for determining how many tasks should be
+  process per round. This property can be changed after a cargo is created to
+  alter the payload on-the-fly.
+* push(task, [callback]) - add a new task to the queue, the callback is called
+  once the worker has finished processing the task.
+  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
+* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
+* empty - a callback that is called when the last item from the queue is given to a worker
+* drain - a callback that is called when the last item from the queue has returned from the worker
+
+__Example__
+
+```js
+// create a cargo object with payload 2
+
+var cargo = async.cargo(function (tasks, callback) {
+    for(var i=0; i<tasks.length; i++){
+      console.log('hello ' + tasks[i].name);
+    }
+    callback();
+}, 2);
+
+
+// add some items
+
+cargo.push({name: 'foo'}, function (err) {
+    console.log('finished processing foo');
+});
+cargo.push({name: 'bar'}, function (err) {
+    console.log('finished processing bar');
+});
+cargo.push({name: 'baz'}, function (err) {
+    console.log('finished processing baz');
+});
+```
+
+---------------------------------------
+
+<a name="auto" />
+### auto(tasks, [callback])
+
+Determines the best order for running functions based on their requirements.
+Each function can optionally depend on other functions being completed first,
+and each function is run as soon as its requirements are satisfied. If any of
+the functions pass an error to their callback, that function will not complete
+(so any other functions depending on it will not run) and the main callback
+will be called immediately with the error. Functions also receive an object
+containing the results of functions which have completed so far.
+
+Note, all functions are called with a results object as a second argument, 
+so it is unsafe to pass functions in the tasks object which cannot handle the
+extra argument. For example, this snippet of code:
+
+```js
+async.auto({
+  readData: async.apply(fs.readFile, 'data.txt', 'utf-8')
+}, callback);
+```
+
+will have the effect of calling readFile with the results object as the last
+argument, which will fail:
+
+```js
+fs.readFile('data.txt', 'utf-8', cb, {});
+```
+
+Instead, wrap the call to readFile in a function which does not forward the 
+results object:
+
+```js
+async.auto({
+  readData: function(cb, results){
+    fs.readFile('data.txt', 'utf-8', cb);
+  }
+}, callback);
+```
+
+__Arguments__
+
+* tasks - An object literal containing named functions or an array of
+  requirements, with the function itself the last item in the array. The key
+  used for each function or array is used when specifying requirements. The 
+  function receives two arguments: (1) a callback(err, result) which must be 
+  called when finished, passing an error (which can be null) and the result of 
+  the function's execution, and (2) a results object, containing the results of
+  the previously executed functions.
+* callback(err, results) - An optional callback which is called when all the
+  tasks have been completed. The callback will receive an error as an argument
+  if any tasks pass an error to their callback. Results will always be passed
+	but if an error occurred, no other tasks will be performed, and the results
+	object will only contain partial results.
+  
+
+__Example__
+
+```js
+async.auto({
+    get_data: function(callback){
+        // async code to get some data
+    },
+    make_folder: function(callback){
+        // async code to create a directory to store a file in
+        // this is run at the same time as getting the data
+    },
+    write_file: ['get_data', 'make_folder', function(callback){
+        // once there is some data and the directory exists,
+        // write the data to a file in the directory
+        callback(null, filename);
+    }],
+    email_link: ['write_file', function(callback, results){
+        // once the file is written let's email a link to it...
+        // results.write_file contains the filename returned by write_file.
+    }]
+});
+```
+
+This is a fairly trivial example, but to do this using the basic parallel and
+series functions would look like this:
+
+```js
+async.parallel([
+    function(callback){
+        // async code to get some data
+    },
+    function(callback){
+        // async code to create a directory to store a file in
+        // this is run at the same time as getting the data
+    }
+],
+function(err, results){
+    async.series([
+        function(callback){
+            // once there is some data and the directory exists,
+            // write the data to a file in the directory
+        },
+        function(callback){
+            // once the file is written let's email a link to it...
+        }
+    ]);
+});
+```
+
+For a complicated series of async tasks using the auto function makes adding
+new tasks much easier and makes the code more readable.
+
+
+---------------------------------------
+
+<a name="iterator" />
+### iterator(tasks)
+
+Creates an iterator function which calls the next function in the array,
+returning a continuation to call the next one after that. It's also possible to
+'peek' the next iterator by doing iterator.next().
+
+This function is used internally by the async module but can be useful when
+you want to manually control the flow of functions in series.
+
+__Arguments__
+
+* tasks - An array of functions to run.
+
+__Example__
+
+```js
+var iterator = async.iterator([
+    function(){ sys.p('one'); },
+    function(){ sys.p('two'); },
+    function(){ sys.p('three'); }
+]);
+
+node> var iterator2 = iterator();
+'one'
+node> var iterator3 = iterator2();
+'two'
+node> iterator3();
+'three'
+node> var nextfn = iterator2.next();
+node> nextfn();
+'three'
+```
+
+---------------------------------------
+
+<a name="apply" />
+### apply(function, arguments..)
+
+Creates a continuation function with some arguments already applied, a useful
+shorthand when combined with other control flow functions. Any arguments
+passed to the returned function are added to the arguments originally passed
+to apply.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to automatically apply when the
+  continuation is called.
+
+__Example__
+
+```js
+// using apply
+
+async.parallel([
+    async.apply(fs.writeFile, 'testfile1', 'test1'),
+    async.apply(fs.writeFile, 'testfile2', 'test2'),
+]);
+
+
+// the same process without using apply
+
+async.parallel([
+    function(callback){
+        fs.writeFile('testfile1', 'test1', callback);
+    },
+    function(callback){
+        fs.writeFile('testfile2', 'test2', callback);
+    }
+]);
+```
+
+It's possible to pass any number of additional arguments when calling the
+continuation:
+
+```js
+node> var fn = async.apply(sys.puts, 'one');
+node> fn('two', 'three');
+one
+two
+three
+```
+
+---------------------------------------
+
+<a name="nextTick" />
+### nextTick(callback)
+
+Calls the callback on a later loop around the event loop. In node.js this just
+calls process.nextTick, in the browser it falls back to setImmediate(callback)
+if available, otherwise setTimeout(callback, 0), which means other higher priority
+events may precede the execution of the callback.
+
+This is used internally for browser-compatibility purposes.
+
+__Arguments__
+
+* callback - The function to call on a later loop around the event loop.
+
+__Example__
+
+```js
+var call_order = [];
+async.nextTick(function(){
+    call_order.push('two');
+    // call_order now equals ['one','two']
+});
+call_order.push('one')
+```
+
+<a name="times" />
+### times(n, callback)
+
+Calls the callback n times and accumulates results in the same manner
+you would use with async.map.
+
+__Arguments__
+
+* n - The number of times to run the function.
+* callback - The function to call n times.
+
+__Example__
+
+```js
+// Pretend this is some complicated async factory
+var createUser = function(id, callback) {
+  callback(null, {
+    id: 'user' + id
+  })
+}
+// generate 5 users
+async.times(5, function(n, next){
+    createUser(n, function(err, user) {
+      next(err, user)
+    })
+}, function(err, users) {
+  // we should now have 5 users
+});
+```
+
+<a name="timesSeries" />
+### timesSeries(n, callback)
+
+The same as times only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+
+## Utils
+
+<a name="memoize" />
+### memoize(fn, [hasher])
+
+Caches the results of an async function. When creating a hash to store function
+results against, the callback is omitted from the hash and an optional hash
+function can be used.
+
+The cache of results is exposed as the `memo` property of the function returned
+by `memoize`.
+
+__Arguments__
+
+* fn - the function you to proxy and cache results from.
+* hasher - an optional function for generating a custom hash for storing
+  results, it has all the arguments applied to it apart from the callback, and
+  must be synchronous.
+
+__Example__
+
+```js
+var slow_fn = function (name, callback) {
+    // do something
+    callback(null, result);
+};
+var fn = async.memoize(slow_fn);
+
+// fn can now be used as if it were slow_fn
+fn('some name', function () {
+    // callback
+});
+```
+
+<a name="unmemoize" />
+### unmemoize(fn)
+
+Undoes a memoized function, reverting it to the original, unmemoized
+form. Comes handy in tests.
+
+__Arguments__
+
+* fn - the memoized function
+
+<a name="log" />
+### log(function, arguments)
+
+Logs the result of an async function to the console. Only works in node.js or
+in browsers that support console.log and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.log is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+```js
+var hello = function(name, callback){
+    setTimeout(function(){
+        callback(null, 'hello ' + name);
+    }, 1000);
+};
+```
+```js
+node> async.log(hello, 'world');
+'hello world'
+```
+
+---------------------------------------
+
+<a name="dir" />
+### dir(function, arguments)
+
+Logs the result of an async function to the console using console.dir to
+display the properties of the resulting object. Only works in node.js or
+in browsers that support console.dir and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.dir is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+```js
+var hello = function(name, callback){
+    setTimeout(function(){
+        callback(null, {hello: name});
+    }, 1000);
+};
+```
+```js
+node> async.dir(hello, 'world');
+{hello: 'world'}
+```
+
+---------------------------------------
+
+<a name="noConflict" />
+### noConflict()
+
+Changes the value of async back to its original value, returning a reference to the
+async object.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/component.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/component.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/component.json	(revision 533)
@@ -0,0 +1,11 @@
+{
+  "name": "async",
+  "repo": "caolan/async",
+  "description": "Higher-order functions and common patterns for asynchronous code",
+  "version": "0.1.23",
+  "keywords": [],
+  "dependencies": {},
+  "development": {},
+  "main": "lib/async.js",
+  "scripts": [ "lib/async.js" ]
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/lib/async.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/lib/async.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/lib/async.js	(revision 533)
@@ -0,0 +1,958 @@
+/*global setImmediate: false, setTimeout: false, console: false */
+(function () {
+
+    var async = {};
+
+    // global on the server, window in the browser
+    var root, previous_async;
+
+    root = this;
+    if (root != null) {
+      previous_async = root.async;
+    }
+
+    async.noConflict = function () {
+        root.async = previous_async;
+        return async;
+    };
+
+    function only_once(fn) {
+        var called = false;
+        return function() {
+            if (called) throw new Error("Callback was already called.");
+            called = true;
+            fn.apply(root, arguments);
+        }
+    }
+
+    //// cross-browser compatiblity functions ////
+
+    var _each = function (arr, iterator) {
+        if (arr.forEach) {
+            return arr.forEach(iterator);
+        }
+        for (var i = 0; i < arr.length; i += 1) {
+            iterator(arr[i], i, arr);
+        }
+    };
+
+    var _map = function (arr, iterator) {
+        if (arr.map) {
+            return arr.map(iterator);
+        }
+        var results = [];
+        _each(arr, function (x, i, a) {
+            results.push(iterator(x, i, a));
+        });
+        return results;
+    };
+
+    var _reduce = function (arr, iterator, memo) {
+        if (arr.reduce) {
+            return arr.reduce(iterator, memo);
+        }
+        _each(arr, function (x, i, a) {
+            memo = iterator(memo, x, i, a);
+        });
+        return memo;
+    };
+
+    var _keys = function (obj) {
+        if (Object.keys) {
+            return Object.keys(obj);
+        }
+        var keys = [];
+        for (var k in obj) {
+            if (obj.hasOwnProperty(k)) {
+                keys.push(k);
+            }
+        }
+        return keys;
+    };
+
+    //// exported async module functions ////
+
+    //// nextTick implementation with browser-compatible fallback ////
+    if (typeof process === 'undefined' || !(process.nextTick)) {
+        if (typeof setImmediate === 'function') {
+            async.nextTick = function (fn) {
+                // not a direct alias for IE10 compatibility
+                setImmediate(fn);
+            };
+            async.setImmediate = async.nextTick;
+        }
+        else {
+            async.nextTick = function (fn) {
+                setTimeout(fn, 0);
+            };
+            async.setImmediate = async.nextTick;
+        }
+    }
+    else {
+        async.nextTick = process.nextTick;
+        if (typeof setImmediate !== 'undefined') {
+            async.setImmediate = function (fn) {
+              // not a direct alias for IE10 compatibility
+              setImmediate(fn);
+            };
+        }
+        else {
+            async.setImmediate = async.nextTick;
+        }
+    }
+
+    async.each = function (arr, iterator, callback) {
+        callback = callback || function () {};
+        if (!arr.length) {
+            return callback();
+        }
+        var completed = 0;
+        _each(arr, function (x) {
+            iterator(x, only_once(function (err) {
+                if (err) {
+                    callback(err);
+                    callback = function () {};
+                }
+                else {
+                    completed += 1;
+                    if (completed >= arr.length) {
+                        callback(null);
+                    }
+                }
+            }));
+        });
+    };
+    async.forEach = async.each;
+
+    async.eachSeries = function (arr, iterator, callback) {
+        callback = callback || function () {};
+        if (!arr.length) {
+            return callback();
+        }
+        var completed = 0;
+        var iterate = function () {
+            iterator(arr[completed], function (err) {
+                if (err) {
+                    callback(err);
+                    callback = function () {};
+                }
+                else {
+                    completed += 1;
+                    if (completed >= arr.length) {
+                        callback(null);
+                    }
+                    else {
+                        iterate();
+                    }
+                }
+            });
+        };
+        iterate();
+    };
+    async.forEachSeries = async.eachSeries;
+
+    async.eachLimit = function (arr, limit, iterator, callback) {
+        var fn = _eachLimit(limit);
+        fn.apply(null, [arr, iterator, callback]);
+    };
+    async.forEachLimit = async.eachLimit;
+
+    var _eachLimit = function (limit) {
+
+        return function (arr, iterator, callback) {
+            callback = callback || function () {};
+            if (!arr.length || limit <= 0) {
+                return callback();
+            }
+            var completed = 0;
+            var started = 0;
+            var running = 0;
+
+            (function replenish () {
+                if (completed >= arr.length) {
+                    return callback();
+                }
+
+                while (running < limit && started < arr.length) {
+                    started += 1;
+                    running += 1;
+                    iterator(arr[started - 1], function (err) {
+                        if (err) {
+                            callback(err);
+                            callback = function () {};
+                        }
+                        else {
+                            completed += 1;
+                            running -= 1;
+                            if (completed >= arr.length) {
+                                callback();
+                            }
+                            else {
+                                replenish();
+                            }
+                        }
+                    });
+                }
+            })();
+        };
+    };
+
+
+    var doParallel = function (fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [async.each].concat(args));
+        };
+    };
+    var doParallelLimit = function(limit, fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [_eachLimit(limit)].concat(args));
+        };
+    };
+    var doSeries = function (fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [async.eachSeries].concat(args));
+        };
+    };
+
+
+    var _asyncMap = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (err, v) {
+                results[x.index] = v;
+                callback(err);
+            });
+        }, function (err) {
+            callback(err, results);
+        });
+    };
+    async.map = doParallel(_asyncMap);
+    async.mapSeries = doSeries(_asyncMap);
+    async.mapLimit = function (arr, limit, iterator, callback) {
+        return _mapLimit(limit)(arr, iterator, callback);
+    };
+
+    var _mapLimit = function(limit) {
+        return doParallelLimit(limit, _asyncMap);
+    };
+
+    // reduce only has a series version, as doing reduce in parallel won't
+    // work in many situations.
+    async.reduce = function (arr, memo, iterator, callback) {
+        async.eachSeries(arr, function (x, callback) {
+            iterator(memo, x, function (err, v) {
+                memo = v;
+                callback(err);
+            });
+        }, function (err) {
+            callback(err, memo);
+        });
+    };
+    // inject alias
+    async.inject = async.reduce;
+    // foldl alias
+    async.foldl = async.reduce;
+
+    async.reduceRight = function (arr, memo, iterator, callback) {
+        var reversed = _map(arr, function (x) {
+            return x;
+        }).reverse();
+        async.reduce(reversed, memo, iterator, callback);
+    };
+    // foldr alias
+    async.foldr = async.reduceRight;
+
+    var _filter = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (v) {
+                if (v) {
+                    results.push(x);
+                }
+                callback();
+            });
+        }, function (err) {
+            callback(_map(results.sort(function (a, b) {
+                return a.index - b.index;
+            }), function (x) {
+                return x.value;
+            }));
+        });
+    };
+    async.filter = doParallel(_filter);
+    async.filterSeries = doSeries(_filter);
+    // select alias
+    async.select = async.filter;
+    async.selectSeries = async.filterSeries;
+
+    var _reject = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (v) {
+                if (!v) {
+                    results.push(x);
+                }
+                callback();
+            });
+        }, function (err) {
+            callback(_map(results.sort(function (a, b) {
+                return a.index - b.index;
+            }), function (x) {
+                return x.value;
+            }));
+        });
+    };
+    async.reject = doParallel(_reject);
+    async.rejectSeries = doSeries(_reject);
+
+    var _detect = function (eachfn, arr, iterator, main_callback) {
+        eachfn(arr, function (x, callback) {
+            iterator(x, function (result) {
+                if (result) {
+                    main_callback(x);
+                    main_callback = function () {};
+                }
+                else {
+                    callback();
+                }
+            });
+        }, function (err) {
+            main_callback();
+        });
+    };
+    async.detect = doParallel(_detect);
+    async.detectSeries = doSeries(_detect);
+
+    async.some = function (arr, iterator, main_callback) {
+        async.each(arr, function (x, callback) {
+            iterator(x, function (v) {
+                if (v) {
+                    main_callback(true);
+                    main_callback = function () {};
+                }
+                callback();
+            });
+        }, function (err) {
+            main_callback(false);
+        });
+    };
+    // any alias
+    async.any = async.some;
+
+    async.every = function (arr, iterator, main_callback) {
+        async.each(arr, function (x, callback) {
+            iterator(x, function (v) {
+                if (!v) {
+                    main_callback(false);
+                    main_callback = function () {};
+                }
+                callback();
+            });
+        }, function (err) {
+            main_callback(true);
+        });
+    };
+    // all alias
+    async.all = async.every;
+
+    async.sortBy = function (arr, iterator, callback) {
+        async.map(arr, function (x, callback) {
+            iterator(x, function (err, criteria) {
+                if (err) {
+                    callback(err);
+                }
+                else {
+                    callback(null, {value: x, criteria: criteria});
+                }
+            });
+        }, function (err, results) {
+            if (err) {
+                return callback(err);
+            }
+            else {
+                var fn = function (left, right) {
+                    var a = left.criteria, b = right.criteria;
+                    return a < b ? -1 : a > b ? 1 : 0;
+                };
+                callback(null, _map(results.sort(fn), function (x) {
+                    return x.value;
+                }));
+            }
+        });
+    };
+
+    async.auto = function (tasks, callback) {
+        callback = callback || function () {};
+        var keys = _keys(tasks);
+        if (!keys.length) {
+            return callback(null);
+        }
+
+        var results = {};
+
+        var listeners = [];
+        var addListener = function (fn) {
+            listeners.unshift(fn);
+        };
+        var removeListener = function (fn) {
+            for (var i = 0; i < listeners.length; i += 1) {
+                if (listeners[i] === fn) {
+                    listeners.splice(i, 1);
+                    return;
+                }
+            }
+        };
+        var taskComplete = function () {
+            _each(listeners.slice(0), function (fn) {
+                fn();
+            });
+        };
+
+        addListener(function () {
+            if (_keys(results).length === keys.length) {
+                callback(null, results);
+                callback = function () {};
+            }
+        });
+
+        _each(keys, function (k) {
+            var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
+            var taskCallback = function (err) {
+                var args = Array.prototype.slice.call(arguments, 1);
+                if (args.length <= 1) {
+                    args = args[0];
+                }
+                if (err) {
+                    var safeResults = {};
+                    _each(_keys(results), function(rkey) {
+                        safeResults[rkey] = results[rkey];
+                    });
+                    safeResults[k] = args;
+                    callback(err, safeResults);
+                    // stop subsequent errors hitting callback multiple times
+                    callback = function () {};
+                }
+                else {
+                    results[k] = args;
+                    async.setImmediate(taskComplete);
+                }
+            };
+            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
+            var ready = function () {
+                return _reduce(requires, function (a, x) {
+                    return (a && results.hasOwnProperty(x));
+                }, true) && !results.hasOwnProperty(k);
+            };
+            if (ready()) {
+                task[task.length - 1](taskCallback, results);
+            }
+            else {
+                var listener = function () {
+                    if (ready()) {
+                        removeListener(listener);
+                        task[task.length - 1](taskCallback, results);
+                    }
+                };
+                addListener(listener);
+            }
+        });
+    };
+
+    async.waterfall = function (tasks, callback) {
+        callback = callback || function () {};
+        if (tasks.constructor !== Array) {
+          var err = new Error('First argument to waterfall must be an array of functions');
+          return callback(err);
+        }
+        if (!tasks.length) {
+            return callback();
+        }
+        var wrapIterator = function (iterator) {
+            return function (err) {
+                if (err) {
+                    callback.apply(null, arguments);
+                    callback = function () {};
+                }
+                else {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    var next = iterator.next();
+                    if (next) {
+                        args.push(wrapIterator(next));
+                    }
+                    else {
+                        args.push(callback);
+                    }
+                    async.setImmediate(function () {
+                        iterator.apply(null, args);
+                    });
+                }
+            };
+        };
+        wrapIterator(async.iterator(tasks))();
+    };
+
+    var _parallel = function(eachfn, tasks, callback) {
+        callback = callback || function () {};
+        if (tasks.constructor === Array) {
+            eachfn.map(tasks, function (fn, callback) {
+                if (fn) {
+                    fn(function (err) {
+                        var args = Array.prototype.slice.call(arguments, 1);
+                        if (args.length <= 1) {
+                            args = args[0];
+                        }
+                        callback.call(null, err, args);
+                    });
+                }
+            }, callback);
+        }
+        else {
+            var results = {};
+            eachfn.each(_keys(tasks), function (k, callback) {
+                tasks[k](function (err) {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    if (args.length <= 1) {
+                        args = args[0];
+                    }
+                    results[k] = args;
+                    callback(err);
+                });
+            }, function (err) {
+                callback(err, results);
+            });
+        }
+    };
+
+    async.parallel = function (tasks, callback) {
+        _parallel({ map: async.map, each: async.each }, tasks, callback);
+    };
+
+    async.parallelLimit = function(tasks, limit, callback) {
+        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
+    };
+
+    async.series = function (tasks, callback) {
+        callback = callback || function () {};
+        if (tasks.constructor === Array) {
+            async.mapSeries(tasks, function (fn, callback) {
+                if (fn) {
+                    fn(function (err) {
+                        var args = Array.prototype.slice.call(arguments, 1);
+                        if (args.length <= 1) {
+                            args = args[0];
+                        }
+                        callback.call(null, err, args);
+                    });
+                }
+            }, callback);
+        }
+        else {
+            var results = {};
+            async.eachSeries(_keys(tasks), function (k, callback) {
+                tasks[k](function (err) {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    if (args.length <= 1) {
+                        args = args[0];
+                    }
+                    results[k] = args;
+                    callback(err);
+                });
+            }, function (err) {
+                callback(err, results);
+            });
+        }
+    };
+
+    async.iterator = function (tasks) {
+        var makeCallback = function (index) {
+            var fn = function () {
+                if (tasks.length) {
+                    tasks[index].apply(null, arguments);
+                }
+                return fn.next();
+            };
+            fn.next = function () {
+                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
+            };
+            return fn;
+        };
+        return makeCallback(0);
+    };
+
+    async.apply = function (fn) {
+        var args = Array.prototype.slice.call(arguments, 1);
+        return function () {
+            return fn.apply(
+                null, args.concat(Array.prototype.slice.call(arguments))
+            );
+        };
+    };
+
+    var _concat = function (eachfn, arr, fn, callback) {
+        var r = [];
+        eachfn(arr, function (x, cb) {
+            fn(x, function (err, y) {
+                r = r.concat(y || []);
+                cb(err);
+            });
+        }, function (err) {
+            callback(err, r);
+        });
+    };
+    async.concat = doParallel(_concat);
+    async.concatSeries = doSeries(_concat);
+
+    async.whilst = function (test, iterator, callback) {
+        if (test()) {
+            iterator(function (err) {
+                if (err) {
+                    return callback(err);
+                }
+                async.whilst(test, iterator, callback);
+            });
+        }
+        else {
+            callback();
+        }
+    };
+
+    async.doWhilst = function (iterator, test, callback) {
+        iterator(function (err) {
+            if (err) {
+                return callback(err);
+            }
+            if (test()) {
+                async.doWhilst(iterator, test, callback);
+            }
+            else {
+                callback();
+            }
+        });
+    };
+
+    async.until = function (test, iterator, callback) {
+        if (!test()) {
+            iterator(function (err) {
+                if (err) {
+                    return callback(err);
+                }
+                async.until(test, iterator, callback);
+            });
+        }
+        else {
+            callback();
+        }
+    };
+
+    async.doUntil = function (iterator, test, callback) {
+        iterator(function (err) {
+            if (err) {
+                return callback(err);
+            }
+            if (!test()) {
+                async.doUntil(iterator, test, callback);
+            }
+            else {
+                callback();
+            }
+        });
+    };
+
+    async.queue = function (worker, concurrency) {
+        if (concurrency === undefined) {
+            concurrency = 1;
+        }
+        function _insert(q, data, pos, callback) {
+          if(data.constructor !== Array) {
+              data = [data];
+          }
+          _each(data, function(task) {
+              var item = {
+                  data: task,
+                  callback: typeof callback === 'function' ? callback : null
+              };
+
+              if (pos) {
+                q.tasks.unshift(item);
+              } else {
+                q.tasks.push(item);
+              }
+
+              if (q.saturated && q.tasks.length === concurrency) {
+                  q.saturated();
+              }
+              async.setImmediate(q.process);
+          });
+        }
+
+        var workers = 0;
+        var q = {
+            tasks: [],
+            concurrency: concurrency,
+            saturated: null,
+            empty: null,
+            drain: null,
+            push: function (data, callback) {
+              _insert(q, data, false, callback);
+            },
+            unshift: function (data, callback) {
+              _insert(q, data, true, callback);
+            },
+            process: function () {
+                if (workers < q.concurrency && q.tasks.length) {
+                    var task = q.tasks.shift();
+                    if (q.empty && q.tasks.length === 0) {
+                        q.empty();
+                    }
+                    workers += 1;
+                    var next = function () {
+                        workers -= 1;
+                        if (task.callback) {
+                            task.callback.apply(task, arguments);
+                        }
+                        if (q.drain && q.tasks.length + workers === 0) {
+                            q.drain();
+                        }
+                        q.process();
+                    };
+                    var cb = only_once(next);
+                    worker(task.data, cb);
+                }
+            },
+            length: function () {
+                return q.tasks.length;
+            },
+            running: function () {
+                return workers;
+            }
+        };
+        return q;
+    };
+
+    async.cargo = function (worker, payload) {
+        var working     = false,
+            tasks       = [];
+
+        var cargo = {
+            tasks: tasks,
+            payload: payload,
+            saturated: null,
+            empty: null,
+            drain: null,
+            push: function (data, callback) {
+                if(data.constructor !== Array) {
+                    data = [data];
+                }
+                _each(data, function(task) {
+                    tasks.push({
+                        data: task,
+                        callback: typeof callback === 'function' ? callback : null
+                    });
+                    if (cargo.saturated && tasks.length === payload) {
+                        cargo.saturated();
+                    }
+                });
+                async.setImmediate(cargo.process);
+            },
+            process: function process() {
+                if (working) return;
+                if (tasks.length === 0) {
+                    if(cargo.drain) cargo.drain();
+                    return;
+                }
+
+                var ts = typeof payload === 'number'
+                            ? tasks.splice(0, payload)
+                            : tasks.splice(0);
+
+                var ds = _map(ts, function (task) {
+                    return task.data;
+                });
+
+                if(cargo.empty) cargo.empty();
+                working = true;
+                worker(ds, function () {
+                    working = false;
+
+                    var args = arguments;
+                    _each(ts, function (data) {
+                        if (data.callback) {
+                            data.callback.apply(null, args);
+                        }
+                    });
+
+                    process();
+                });
+            },
+            length: function () {
+                return tasks.length;
+            },
+            running: function () {
+                return working;
+            }
+        };
+        return cargo;
+    };
+
+    var _console_fn = function (name) {
+        return function (fn) {
+            var args = Array.prototype.slice.call(arguments, 1);
+            fn.apply(null, args.concat([function (err) {
+                var args = Array.prototype.slice.call(arguments, 1);
+                if (typeof console !== 'undefined') {
+                    if (err) {
+                        if (console.error) {
+                            console.error(err);
+                        }
+                    }
+                    else if (console[name]) {
+                        _each(args, function (x) {
+                            console[name](x);
+                        });
+                    }
+                }
+            }]));
+        };
+    };
+    async.log = _console_fn('log');
+    async.dir = _console_fn('dir');
+    /*async.info = _console_fn('info');
+    async.warn = _console_fn('warn');
+    async.error = _console_fn('error');*/
+
+    async.memoize = function (fn, hasher) {
+        var memo = {};
+        var queues = {};
+        hasher = hasher || function (x) {
+            return x;
+        };
+        var memoized = function () {
+            var args = Array.prototype.slice.call(arguments);
+            var callback = args.pop();
+            var key = hasher.apply(null, args);
+            if (key in memo) {
+                callback.apply(null, memo[key]);
+            }
+            else if (key in queues) {
+                queues[key].push(callback);
+            }
+            else {
+                queues[key] = [callback];
+                fn.apply(null, args.concat([function () {
+                    memo[key] = arguments;
+                    var q = queues[key];
+                    delete queues[key];
+                    for (var i = 0, l = q.length; i < l; i++) {
+                      q[i].apply(null, arguments);
+                    }
+                }]));
+            }
+        };
+        memoized.memo = memo;
+        memoized.unmemoized = fn;
+        return memoized;
+    };
+
+    async.unmemoize = function (fn) {
+      return function () {
+        return (fn.unmemoized || fn).apply(null, arguments);
+      };
+    };
+
+    async.times = function (count, iterator, callback) {
+        var counter = [];
+        for (var i = 0; i < count; i++) {
+            counter.push(i);
+        }
+        return async.map(counter, iterator, callback);
+    };
+
+    async.timesSeries = function (count, iterator, callback) {
+        var counter = [];
+        for (var i = 0; i < count; i++) {
+            counter.push(i);
+        }
+        return async.mapSeries(counter, iterator, callback);
+    };
+
+    async.compose = function (/* functions... */) {
+        var fns = Array.prototype.reverse.call(arguments);
+        return function () {
+            var that = this;
+            var args = Array.prototype.slice.call(arguments);
+            var callback = args.pop();
+            async.reduce(fns, args, function (newargs, fn, cb) {
+                fn.apply(that, newargs.concat([function () {
+                    var err = arguments[0];
+                    var nextargs = Array.prototype.slice.call(arguments, 1);
+                    cb(err, nextargs);
+                }]))
+            },
+            function (err, results) {
+                callback.apply(that, [err].concat(results));
+            });
+        };
+    };
+
+    var _applyEach = function (eachfn, fns /*args...*/) {
+        var go = function () {
+            var that = this;
+            var args = Array.prototype.slice.call(arguments);
+            var callback = args.pop();
+            return eachfn(fns, function (fn, cb) {
+                fn.apply(that, args.concat([cb]));
+            },
+            callback);
+        };
+        if (arguments.length > 2) {
+            var args = Array.prototype.slice.call(arguments, 2);
+            return go.apply(this, args);
+        }
+        else {
+            return go;
+        }
+    };
+    async.applyEach = doParallel(_applyEach);
+    async.applyEachSeries = doSeries(_applyEach);
+
+    async.forever = function (fn, callback) {
+        function next(err) {
+            if (err) {
+                if (callback) {
+                    return callback(err);
+                }
+                throw err;
+            }
+            fn(next);
+        }
+        next();
+    };
+
+    // AMD / RequireJS
+    if (typeof define !== 'undefined' && define.amd) {
+        define([], function () {
+            return async;
+        });
+    }
+    // Node.js
+    else if (typeof module !== 'undefined' && module.exports) {
+        module.exports = async;
+    }
+    // included directly via <script> tag
+    else {
+        root.async = async;
+    }
+
+}());
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/async/package.json	(revision 533)
@@ -0,0 +1,43 @@
+{
+  "name": "async",
+  "description": "Higher-order functions and common patterns for asynchronous code",
+  "main": "./lib/async",
+  "author": {
+    "name": "Caolan McMahon"
+  },
+  "version": "0.2.10",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/caolan/async.git"
+  },
+  "bugs": {
+    "url": "https://github.com/caolan/async/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://github.com/caolan/async/raw/master/LICENSE"
+    }
+  ],
+  "devDependencies": {
+    "nodeunit": ">0.0.0",
+    "uglify-js": "1.2.x",
+    "nodelint": ">0.0.0"
+  },
+  "jam": {
+    "main": "lib/async.js",
+    "include": [
+      "lib/async.js",
+      "README.md",
+      "LICENSE"
+    ]
+  },
+  "scripts": {
+    "test": "nodeunit test/test-async.js"
+  },
+  "readme": "# Async.js\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [node.js](http://nodejs.org), it can also be used directly in the\nbrowser. Also supports [component](https://github.com/component/component).\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, eachâŠ) as well as some common patterns\nfor asynchronous control flow (parallel, series, waterfallâŠ). All these\nfunctions assume you follow the node.js convention of providing a single\ncallback as the last argument of your async function.\n\n\n## Quick Examples\n\n```javascript\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n    // results is now an array of stats for each file\n});\n\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n    // results now equals an array of the existing files\n});\n\nasync.parallel([\n    function(){ ... },\n    function(){ ... }\n], callback);\n\nasync.series([\n    function(){ ... },\n    function(){ ... }\n]);\n```\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n## Common Pitfalls\n\n### Binding a context to an iterator\n\nThis section is really about bind, not about async. If you are wondering how to\nmake async execute your iterators in a given context, or are confused as to why\na method of another library isn't working as an iterator, study this example:\n\n```js\n// Here is a simple object with an (unnecessarily roundabout) squaring method\nvar AsyncSquaringLibrary = {\n  squareExponent: 2,\n  square: function(number, callback){ \n    var result = Math.pow(number, this.squareExponent);\n    setTimeout(function(){\n      callback(null, result);\n    }, 200);\n  }\n};\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){\n  // result is [NaN, NaN, NaN]\n  // This fails because the `this.squareExponent` expression in the square\n  // function is not evaluated in the context of AsyncSquaringLibrary, and is\n  // therefore undefined.\n});\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){\n  // result is [1, 4, 9]\n  // With the help of bind we can attach a context to the iterator before\n  // passing it to async. Now the square function will be executed in its \n  // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`\n  // will be as expected.\n});\n```\n\n## Download\n\nThe source is available for download from\n[GitHub](http://github.com/caolan/async).\nAlternatively, you can install using Node Package Manager (npm):\n\n    npm install async\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed\n\n## In the Browser\n\nSo far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n```html\n<script type=\"text/javascript\" src=\"async.js\"></script>\n<script type=\"text/javascript\">\n\n    async.map(data, asyncProcess, function(err, results){\n        alert(results);\n    });\n\n</script>\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [eachSeries](#eachSeries)\n* [eachLimit](#eachLimit)\n* [map](#map)\n* [mapSeries](#mapSeries)\n* [mapLimit](#mapLimit)\n* [filter](#filter)\n* [filterSeries](#filterSeries)\n* [reject](#reject)\n* [rejectSeries](#rejectSeries)\n* [reduce](#reduce)\n* [reduceRight](#reduceRight)\n* [detect](#detect)\n* [detectSeries](#detectSeries)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n* [concatSeries](#concatSeries)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [parallelLimit](#parallellimittasks-limit-callback)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [applyEachSeries](#applyEachSeries)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n<a name=\"forEach\" />\n<a name=\"each\" />\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err) which must be called once it has \n  completed. If no error has occured, the callback should be run without \n  arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n  have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n    // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n<a name=\"forEachSeries\" />\n<a name=\"eachSeries\" />\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n<a name=\"forEachLimit\" />\n<a name=\"eachLimit\" />\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err) which must be called once it has \n  completed. If no error has occured, the callback should be run without \n  arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n  have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n    // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n<a name=\"map\" />\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, transformed) which must be called once \n  it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is an array of the\n  transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n    // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n<a name=\"mapSeries\" />\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n<a name=\"mapLimit\" />\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, transformed) which must be called once \n  it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is an array of the\n  transformed items from the original array.\n\n__Example__\n\n```js\nasync.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){\n    // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n<a name=\"filter\" />\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n  functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n    // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n<a name=\"filterSeries\" />\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n<a name=\"reject\" />\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n<a name=\"rejectSeries\" />\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n<a name=\"reduce\" />\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n  array to produce the next step in the reduction. The iterator is passed a\n  callback(err, reduction) which accepts an optional error as its first \n  argument, and the state of the reduction as the second. If an error is \n  passed to the callback, the reduction is stopped and the main callback is \n  immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n  functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n    // pointless async:\n    process.nextTick(function(){\n        callback(null, memo + item)\n    });\n}, function(err, result){\n    // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n<a name=\"reduceRight\" />\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n<a name=\"detect\" />\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n  true, or after all the iterator functions have finished. Result will be\n  the first item in the array that passes the truth test (iterator) or the\n  value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n    // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n<a name=\"detectSeries\" />\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n<a name=\"sortBy\" />\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, sortValue) which must be called once it\n  has completed with an error (which can be null) and a value to use as the sort\n  criteria.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is the items from\n  the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n    fs.stat(file, function(err, stats){\n        callback(err, stats.mtime);\n    });\n}, function(err, results){\n    // results is now the original array of files sorted by\n    // modified date\n});\n```\n\n---------------------------------------\n\n<a name=\"some\" />\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n  true, or after all the iterator functions have finished. Result will be\n  either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n    // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n<a name=\"every\" />\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n  functions have finished. Result will be either true or false depending on\n  the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n    // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n<a name=\"concat\" />\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, results) which must be called once it \n  has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is an array containing\n  the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n    // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n<a name=\"concatSeries\" />\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n<a name=\"series\" />\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n  a callback(err, result) it must call on completion with an error (which can\n  be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n  have completed. This function gets a results array (or object) containing all \n  the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n    function(callback){\n        // do some stuff ...\n        callback(null, 'one');\n    },\n    function(callback){\n        // do some more stuff ...\n        callback(null, 'two');\n    }\n],\n// optional callback\nfunction(err, results){\n    // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n    one: function(callback){\n        setTimeout(function(){\n            callback(null, 1);\n        }, 200);\n    },\n    two: function(callback){\n        setTimeout(function(){\n            callback(null, 2);\n        }, 100);\n    }\n},\nfunction(err, results) {\n    // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n<a name=\"parallel\" />\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n  a callback(err, result) it must call on completion with an error (which can\n  be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n  have completed. This function gets a results array (or object) containing all \n  the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n    function(callback){\n        setTimeout(function(){\n            callback(null, 'one');\n        }, 200);\n    },\n    function(callback){\n        setTimeout(function(){\n            callback(null, 'two');\n        }, 100);\n    }\n],\n// optional callback\nfunction(err, results){\n    // the results array will equal ['one','two'] even though\n    // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n    one: function(callback){\n        setTimeout(function(){\n            callback(null, 1);\n        }, 200);\n    },\n    two: function(callback){\n        setTimeout(function(){\n            callback(null, 2);\n        }, 100);\n    }\n},\nfunction(err, results) {\n    // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n<a name=\"parallel\" />\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n  a callback(err, result) it must call on completion with an error (which can\n  be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n  have completed. This function gets a results array (or object) containing all \n  the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n<a name=\"whilst\" />\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n  passed a callback(err) which must be called once it has completed with an \n  optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n  execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n    function () { return count < 5; },\n    function (callback) {\n        count++;\n        setTimeout(callback, 1000);\n    },\n    function (err) {\n        // 5 seconds have passed\n    }\n);\n```\n\n---------------------------------------\n\n<a name=\"doWhilst\" />\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n<a name=\"until\" />\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n<a name=\"doUntil\" />\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n<a name=\"forever\" />\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n<a name=\"waterfall\" />\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n  callback(err, result1, result2, ...) it must call on completion. The first\n  argument is an error (which can be null) and any further arguments will be \n  passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n  have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n    function(callback){\n        callback(null, 'one', 'two');\n    },\n    function(arg1, arg2, callback){\n        callback(null, 'three');\n    },\n    function(arg1, callback){\n        // arg1 now equals 'three'\n        callback(null, 'done');\n    }\n], function (err, result) {\n   // result now equals 'done'    \n});\n```\n\n---------------------------------------\n<a name=\"compose\" />\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n    setTimeout(function () {\n        callback(null, n + 1);\n    }, 10);\n}\n\nfunction mul3(n, callback) {\n    setTimeout(function () {\n        callback(null, n * 3);\n    }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n   // result now equals 15\n});\n```\n\n---------------------------------------\n<a name=\"applyEach\" />\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n  functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n    buckets,\n    async.applyEach([enableSearch, updateSchema]),\n    callback\n);\n```\n\n---------------------------------------\n\n<a name=\"applyEachSeries\" />\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n<a name=\"queue\" />\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n  task, which must call its callback(err) argument when finished, with an \n  optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n  run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n  run in parallel. This property can be changed after a queue is created to\n  alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n  once the worker has finished processing the task.\n  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n    console.log('hello ' + task.name);\n    callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n    console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n    console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n    console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n<a name=\"cargo\" />\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n  queued tasks, which must call its callback(err) argument when finished, with \n  an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n  processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n  process per round. This property can be changed after a cargo is created to\n  alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n  once the worker has finished processing the task.\n  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n    for(var i=0; i<tasks.length; i++){\n      console.log('hello ' + tasks[i].name);\n    }\n    callback();\n}, 2);\n\n\n// add some items\n\ncargo.push({name: 'foo'}, function (err) {\n    console.log('finished processing foo');\n});\ncargo.push({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\ncargo.push({name: 'baz'}, function (err) {\n    console.log('finished processing baz');\n});\n```\n\n---------------------------------------\n\n<a name=\"auto\" />\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n  readData: async.apply(fs.readFile, 'data.txt', 'utf-8')\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n  readData: function(cb, results){\n    fs.readFile('data.txt', 'utf-8', cb);\n  }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n  requirements, with the function itself the last item in the array. The key\n  used for each function or array is used when specifying requirements. The \n  function receives two arguments: (1) a callback(err, result) which must be \n  called when finished, passing an error (which can be null) and the result of \n  the function's execution, and (2) a results object, containing the results of\n  the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n  tasks have been completed. The callback will receive an error as an argument\n  if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n  \n\n__Example__\n\n```js\nasync.auto({\n    get_data: function(callback){\n        // async code to get some data\n    },\n    make_folder: function(callback){\n        // async code to create a directory to store a file in\n        // this is run at the same time as getting the data\n    },\n    write_file: ['get_data', 'make_folder', function(callback){\n        // once there is some data and the directory exists,\n        // write the data to a file in the directory\n        callback(null, filename);\n    }],\n    email_link: ['write_file', function(callback, results){\n        // once the file is written let's email a link to it...\n        // results.write_file contains the filename returned by write_file.\n    }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n    function(callback){\n        // async code to get some data\n    },\n    function(callback){\n        // async code to create a directory to store a file in\n        // this is run at the same time as getting the data\n    }\n],\nfunction(err, results){\n    async.series([\n        function(callback){\n            // once there is some data and the directory exists,\n            // write the data to a file in the directory\n        },\n        function(callback){\n            // once the file is written let's email a link to it...\n        }\n    ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n<a name=\"iterator\" />\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n    function(){ sys.p('one'); },\n    function(){ sys.p('two'); },\n    function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n<a name=\"apply\" />\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n  continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n    async.apply(fs.writeFile, 'testfile1', 'test1'),\n    async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n    function(callback){\n        fs.writeFile('testfile1', 'test1', callback);\n    },\n    function(callback){\n        fs.writeFile('testfile2', 'test2', callback);\n    }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n<a name=\"nextTick\" />\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n    call_order.push('two');\n    // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n<a name=\"times\" />\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n  callback(null, {\n    id: 'user' + id\n  })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n    createUser(n, function(err, user) {\n      next(err, user)\n    })\n}, function(err, users) {\n  // we should now have 5 users\n});\n```\n\n<a name=\"timesSeries\" />\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n<a name=\"memoize\" />\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n  results, it has all the arguments applied to it apart from the callback, and\n  must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n    // do something\n    callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n    // callback\n});\n```\n\n<a name=\"unmemoize\" />\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n<a name=\"log\" />\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n    setTimeout(function(){\n        callback(null, 'hello ' + name);\n    }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n<a name=\"dir\" />\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n    setTimeout(function(){\n        callback(null, {hello: name});\n    }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n<a name=\"noConflict\" />\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n",
+  "readmeFilename": "README.md",
+  "homepage": "https://github.com/caolan/async",
+  "_id": "async@0.2.10",
+  "_from": "async@~0.2.9"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/LICENSE-MIT
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/LICENSE-MIT	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/LICENSE-MIT	(revision 533)
@@ -0,0 +1,22 @@
+Copyright (c) 2013 Kyle Robinson Young
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/README.md	(revision 533)
@@ -0,0 +1,180 @@
+# gaze [![Build Status](https://travis-ci.org/shama/gaze.png?branch=master)](https://travis-ci.org/shama/gaze)
+
+A globbing fs.watch wrapper built from the best parts of other fine watch libs.  
+Compatible with Node.js 0.10/0.8, Windows, OSX and Linux.
+
+![gaze](http://dontkry.com/images/repos/gaze.png)
+
+## Usage
+Install the module with: `npm install gaze` or place into your `package.json`
+and run `npm install`.
+
+```javascript
+var gaze = require('gaze');
+
+// Watch all .js files/dirs in process.cwd()
+gaze('**/*.js', function(err, watcher) {
+  // Files have all started watching
+  // watcher === this
+
+  // Get all watched files
+  console.log(this.watched());
+
+  // On file changed
+  this.on('changed', function(filepath) {
+    console.log(filepath + ' was changed');
+  });
+
+  // On file added
+  this.on('added', function(filepath) {
+    console.log(filepath + ' was added');
+  });
+
+  // On file deleted
+  this.on('deleted', function(filepath) {
+    console.log(filepath + ' was deleted');
+  });
+
+  // On changed/added/deleted
+  this.on('all', function(event, filepath) {
+    console.log(filepath + ' was ' + event);
+  });
+
+  // Get watched files with relative paths
+  console.log(this.relative());
+});
+
+// Also accepts an array of patterns
+gaze(['stylesheets/*.css', 'images/**/*.png'], function() {
+  // Add more patterns later to be watched
+  this.add(['js/*.js']);
+});
+```
+
+### Alternate Interface
+
+```javascript
+var Gaze = require('gaze').Gaze;
+
+var gaze = new Gaze('**/*');
+
+// Files have all started watching
+gaze.on('ready', function(watcher) { });
+
+// A file has been added/changed/deleted has occurred
+gaze.on('all', function(event, filepath) { });
+```
+
+### Errors
+
+```javascript
+gaze('**/*', function() {
+  this.on('error', function(err) {
+    // Handle error here
+  });
+});
+```
+
+### Minimatch / Glob
+
+See [isaacs's minimatch](https://github.com/isaacs/minimatch) for more
+information on glob patterns.
+
+## Documentation
+
+### gaze(patterns, [options], callback)
+
+* `patterns` {String|Array} File patterns to be matched
+* `options` {Object}
+* `callback` {Function}
+  * `err` {Error | null}
+  * `watcher` {Object} Instance of the Gaze watcher
+
+### Class: gaze.Gaze
+
+Create a Gaze object by instanting the `gaze.Gaze` class.
+
+```javascript
+var Gaze = require('gaze').Gaze;
+var gaze = new Gaze(pattern, options, callback);
+```
+
+#### Properties
+
+* `options` The options object passed in.
+  * `interval` {integer} Interval to pass to fs.watchFile
+  * `debounceDelay` {integer} Delay for events called in succession for the same
+    file/event
+
+#### Events
+
+* `ready(watcher)` When files have been globbed and watching has begun.
+* `all(event, filepath)` When an `added`, `changed` or `deleted` event occurs.
+* `added(filepath)` When a file has been added to a watch directory.
+* `changed(filepath)` When a file has been changed.
+* `deleted(filepath)` When a file has been deleted.
+* `renamed(newPath, oldPath)` When a file has been renamed.
+* `end()` When the watcher is closed and watches have been removed.
+* `error(err)` When an error occurs.
+* `nomatch` When no files have been matched.
+
+#### Methods
+
+* `emit(event, [...])` Wrapper for the EventEmitter.emit.
+  `added`|`changed`|`deleted` events will also trigger the `all` event.
+* `close()` Unwatch all files and reset the watch instance.
+* `add(patterns, callback)` Adds file(s) patterns to be watched.
+* `remove(filepath)` removes a file or directory from being watched. Does not
+  recurse directories.
+* `watched()` Returns the currently watched files.
+* `relative([dir, unixify])` Returns the currently watched files with relative paths.
+  * `dir` {string} Only return relative files for this directory.
+  * `unixify` {boolean} Return paths with `/` instead of `\\` if on Windows.
+
+## FAQs
+
+### Why Another `fs.watch` Wrapper?
+I liked parts of other `fs.watch` wrappers but none had all the features I
+needed. This lib combines the features I needed from other fine watch libs:
+Speedy data behavior from
+[paulmillr's chokidar](https://github.com/paulmillr/chokidar), API interface
+from [mikeal's watch](https://github.com/mikeal/watch) and file globbing using
+[isaacs's glob](https://github.com/isaacs/node-glob) which is also used by
+[cowboy's Grunt](https://github.com/gruntjs/grunt).
+
+### How do I fix the error `EMFILE: Too many opened files.`?
+This is because of your system's max opened file limit. For OSX the default is
+very low (256). Increase your limit temporarily with `ulimit -n 10480`, the
+number being the new max limit.
+
+## Contributing
+In lieu of a formal styleguide, take care to maintain the existing coding style.
+Add unit tests for any new or changed functionality. Lint and test your code
+using [grunt](http://gruntjs.com/).
+
+## Release History
+* 0.5.1 - Use setImmediate (process.nextTick for node v0.8) to defer ready/nomatch events (@amasad).
+* 0.5.0 - Process is now kept alive while watching files. Emits a nomatch event when no files are matching.
+* 0.4.3 - Track file additions in newly created folders (@brett-shwom).
+* 0.4.2 - Fix .remove() method to remove a single file in a directory (@kaelzhang). Fixing Cannot call method 'call' of undefined (@krasimir). Track new file additions within folders (@brett-shwom).
+* 0.4.1 - Fix watchDir not respecting close in race condition (@chrisirhc).
+* 0.4.0 - Drop support for node v0.6. Use globule for file matching. Avoid node v0.10 path.resolve/join errors. Register new files when added to non-existent folder. Multiple instances can now poll the same files (@jpommerening).
+* 0.3.4 - Code clean up. Fix path must be strings errors (@groner). Fix incorrect added events (@groner).
+* 0.3.3 - Fix for multiple patterns with negate.
+* 0.3.2 - Emit `end` before removeAllListeners.
+* 0.3.1 - Fix added events within subfolder patterns.
+* 0.3.0 - Handle safewrite events, `forceWatchMethod` option removed, bug fixes and watch optimizations (@rgaskill).
+* 0.2.2 - Fix issue where subsequent add calls dont get watched (@samcday). removeAllListeners on close.
+* 0.2.1 - Fix issue with invalid `added` events in current working dir.
+* 0.2.0 - Support and mark folders with `path.sep`. Add `forceWatchMethod` option. Support `renamed` events.
+* 0.1.6 - Recognize the `cwd` option properly
+* 0.1.5 - Catch too many open file errors
+* 0.1.4 - Really fix the race condition with 2 watches
+* 0.1.3 - Fix race condition with 2 watches
+* 0.1.2 - Read triggering changed event fix
+* 0.1.1 - Minor fixes
+* 0.1.0 - Initial release
+
+## License
+Copyright (c) 2013 Kyle Robinson Young  
+Licensed under the MIT license.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/lib/gaze.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/lib/gaze.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/lib/gaze.js	(revision 533)
@@ -0,0 +1,439 @@
+/*
+ * gaze
+ * https://github.com/shama/gaze
+ *
+ * Copyright (c) 2013 Kyle Robinson Young
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+// libs
+var util = require('util');
+var EE = require('events').EventEmitter;
+var fs = require('fs');
+var path = require('path');
+var globule = require('globule');
+var helper = require('./helper');
+
+// shim setImmediate for node v0.8
+var setImmediate = require('timers').setImmediate;
+if (typeof setImmediate !== 'function') {
+  setImmediate = process.nextTick;
+}
+
+// globals
+var delay = 10;
+
+// `Gaze` EventEmitter object to return in the callback
+function Gaze(patterns, opts, done) {
+  var self = this;
+  EE.call(self);
+
+  // If second arg is the callback
+  if (typeof opts === 'function') {
+    done = opts;
+    opts = {};
+  }
+
+  // Default options
+  opts = opts || {};
+  opts.mark = true;
+  opts.interval = opts.interval || 100;
+  opts.debounceDelay = opts.debounceDelay || 500;
+  opts.cwd = opts.cwd || process.cwd();
+  this.options = opts;
+
+  // Default done callback
+  done = done || function() {};
+
+  // Remember our watched dir:files
+  this._watched = Object.create(null);
+
+  // Store watchers
+  this._watchers = Object.create(null);
+
+  // Store watchFile listeners
+  this._pollers = Object.create(null);
+
+  // Store patterns
+  this._patterns = [];
+
+  // Cached events for debouncing
+  this._cached = Object.create(null);
+
+  // Set maxListeners
+  if (this.options.maxListeners) {
+    this.setMaxListeners(this.options.maxListeners);
+    Gaze.super_.prototype.setMaxListeners(this.options.maxListeners);
+    delete this.options.maxListeners;
+  }
+
+  // Initialize the watch on files
+  if (patterns) {
+    this.add(patterns, done);
+  }
+
+  // keep the process alive
+  this._keepalive = setInterval(function() {}, 200);
+
+  return this;
+}
+util.inherits(Gaze, EE);
+
+// Main entry point. Start watching and call done when setup
+module.exports = function gaze(patterns, opts, done) {
+  return new Gaze(patterns, opts, done);
+};
+module.exports.Gaze = Gaze;
+
+// Override the emit function to emit `all` events
+// and debounce on duplicate events per file
+Gaze.prototype.emit = function() {
+  var self = this;
+  var args = arguments;
+
+  var e = args[0];
+  var filepath = args[1];
+  var timeoutId;
+
+  // If not added/deleted/changed/renamed then just emit the event
+  if (e.slice(-2) !== 'ed') {
+    Gaze.super_.prototype.emit.apply(self, args);
+    return this;
+  }
+
+  // Detect rename event, if added and previous deleted is in the cache
+  if (e === 'added') {
+    Object.keys(this._cached).forEach(function(oldFile) {
+      if (self._cached[oldFile].indexOf('deleted') !== -1) {
+        args[0] = e = 'renamed';
+        [].push.call(args, oldFile);
+        delete self._cached[oldFile];
+        return false;
+      }
+    });
+  }
+
+  // If cached doesnt exist, create a delay before running the next
+  // then emit the event
+  var cache = this._cached[filepath] || [];
+  if (cache.indexOf(e) === -1) {
+    helper.objectPush(self._cached, filepath, e);
+    clearTimeout(timeoutId);
+    timeoutId = setTimeout(function() {
+      delete self._cached[filepath];
+    }, this.options.debounceDelay);
+    // Emit the event and `all` event
+    Gaze.super_.prototype.emit.apply(self, args);
+    Gaze.super_.prototype.emit.apply(self, ['all', e].concat([].slice.call(args, 1)));
+  }
+
+  // Detect if new folder added to trigger for matching files within folder
+  if (e === 'added') {
+    if (helper.isDir(filepath)) {
+      fs.readdirSync(filepath).map(function(file) {
+        return path.join(filepath, file);
+      }).filter(function(file) {
+        return globule.isMatch(self._patterns, file, self.options);
+      }).forEach(function(file) {
+        self.emit('added', file);
+      });
+    }
+  }
+
+  return this;
+};
+
+// Close watchers
+Gaze.prototype.close = function(_reset) {
+  var self = this;
+  _reset = _reset === false ? false : true;
+  Object.keys(self._watchers).forEach(function(file) {
+    self._watchers[file].close();
+  });
+  self._watchers = Object.create(null);
+  Object.keys(this._watched).forEach(function(dir) {
+    self._unpollDir(dir);
+  });
+  if (_reset) {
+    self._watched = Object.create(null);
+    setTimeout(function() {
+      self.emit('end');
+      self.removeAllListeners();
+      clearInterval(self._keepalive);
+    }, delay + 100);
+  }
+  return self;
+};
+
+// Add file patterns to be watched
+Gaze.prototype.add = function(files, done) {
+  if (typeof files === 'string') { files = [files]; }
+  this._patterns = helper.unique.apply(null, [this._patterns, files]);
+  files = globule.find(this._patterns, this.options);
+  this._addToWatched(files);
+  this.close(false);
+  this._initWatched(done);
+};
+
+// Dont increment patterns and dont call done if nothing added
+Gaze.prototype._internalAdd = function(file, done) {
+  var files = [];
+  if (helper.isDir(file)) {
+    files = [helper.markDir(file)].concat(globule.find(this._patterns, this.options));
+  } else {
+    if (globule.isMatch(this._patterns, file, this.options)) {
+      files = [file];
+    }
+  }
+  if (files.length > 0) {
+    this._addToWatched(files);
+    this.close(false);
+    this._initWatched(done);
+  }
+};
+
+// Remove file/dir from `watched`
+Gaze.prototype.remove = function(file) {
+  var self = this;
+  if (this._watched[file]) {
+    // is dir, remove all files
+    this._unpollDir(file);
+    delete this._watched[file];
+  } else {
+    // is a file, find and remove
+    Object.keys(this._watched).forEach(function(dir) {
+      var index = self._watched[dir].indexOf(file);
+      if (index !== -1) {
+        self._unpollFile(file);
+        self._watched[dir].splice(index, 1);
+        return false;
+      }
+    });
+  }
+  if (this._watchers[file]) {
+    this._watchers[file].close();
+  }
+  return this;
+};
+
+// Return watched files
+Gaze.prototype.watched = function() {
+  return this._watched;
+};
+
+// Returns `watched` files with relative paths to process.cwd()
+Gaze.prototype.relative = function(dir, unixify) {
+  var self = this;
+  var relative = Object.create(null);
+  var relDir, relFile, unixRelDir;
+  var cwd = this.options.cwd || process.cwd();
+  if (dir === '') { dir = '.'; }
+  dir = helper.markDir(dir);
+  unixify = unixify || false;
+  Object.keys(this._watched).forEach(function(dir) {
+    relDir = path.relative(cwd, dir) + path.sep;
+    if (relDir === path.sep) { relDir = '.'; }
+    unixRelDir = unixify ? helper.unixifyPathSep(relDir) : relDir;
+    relative[unixRelDir] = self._watched[dir].map(function(file) {
+      relFile = path.relative(path.join(cwd, relDir) || '', file || '');
+      if (helper.isDir(file)) {
+        relFile = helper.markDir(relFile);
+      }
+      if (unixify) {
+        relFile = helper.unixifyPathSep(relFile);
+      }
+      return relFile;
+    });
+  });
+  if (dir && unixify) {
+    dir = helper.unixifyPathSep(dir);
+  }
+  return dir ? relative[dir] || [] : relative;
+};
+
+// Adds files and dirs to watched
+Gaze.prototype._addToWatched = function(files) {
+  for (var i = 0; i < files.length; i++) {
+    var file = files[i];
+    var filepath = path.resolve(this.options.cwd, file);
+
+    var dirname = (helper.isDir(file)) ? filepath : path.dirname(filepath);
+    dirname = helper.markDir(dirname);
+
+    // If a new dir is added
+    if (helper.isDir(file) && !(filepath in this._watched)) {
+      helper.objectPush(this._watched, filepath, []);
+    }
+
+    if (file.slice(-1) === '/') { filepath += path.sep; }
+    helper.objectPush(this._watched, path.dirname(filepath) + path.sep, filepath);
+
+    // add folders into the mix
+    var readdir = fs.readdirSync(dirname);
+    for (var j = 0; j < readdir.length; j++) {
+      var dirfile = path.join(dirname, readdir[j]);
+      if (fs.statSync(dirfile).isDirectory()) {
+        helper.objectPush(this._watched, dirname, dirfile + path.sep);
+      }
+    }
+  }
+  return this;
+};
+
+Gaze.prototype._watchDir = function(dir, done) {
+  var self = this;
+  var timeoutId;
+  try {
+    this._watchers[dir] = fs.watch(dir, function(event) {
+      // race condition. Let's give the fs a little time to settle down. so we
+      // don't fire events on non existent files.
+      clearTimeout(timeoutId);
+      timeoutId = setTimeout(function() {
+        // race condition. Ensure that this directory is still being watched
+        // before continuing.
+        if ((dir in self._watchers) && fs.existsSync(dir)) {
+          done(null, dir);
+        }
+      }, delay + 100);
+    });
+  } catch (err) {
+    return this._handleError(err);
+  }
+  return this;
+};
+
+Gaze.prototype._unpollFile = function(file) {
+  if (this._pollers[file]) {
+    fs.unwatchFile(file, this._pollers[file] );
+    delete this._pollers[file];
+  }
+  return this;
+};
+
+Gaze.prototype._unpollDir = function(dir) {
+  this._unpollFile(dir);
+  for (var i = 0; i < this._watched[dir].length; i++) {
+    this._unpollFile(this._watched[dir][i]);
+  }
+};
+
+Gaze.prototype._pollFile = function(file, done) {
+  var opts = { persistent: true, interval: this.options.interval };
+  if (!this._pollers[file]) {
+    this._pollers[file] = function(curr, prev) {
+      done(null, file);
+    };
+    try {
+      fs.watchFile(file, opts, this._pollers[file]);
+    } catch (err) {
+      return this._handleError(err);
+    }
+  }
+  return this;
+};
+
+// Initialize the actual watch on `watched` files
+Gaze.prototype._initWatched = function(done) {
+  var self = this;
+  var cwd = this.options.cwd || process.cwd();
+  var curWatched = Object.keys(self._watched);
+
+  // if no matching files
+  if (curWatched.length < 1) {
+    // Defer to emitting to give a chance to attach event handlers.
+    setImmediate(function () {
+      self.emit('ready', self);
+      if (done) { done.call(self, null, self); }
+      self.emit('nomatch');
+    });
+    return;
+  }
+
+  helper.forEachSeries(curWatched, function(dir, next) {
+    dir = dir || '';
+    var files = self._watched[dir];
+    // Triggered when a watched dir has an event
+    self._watchDir(dir, function(event, dirpath) {
+      var relDir = cwd === dir ? '.' : path.relative(cwd, dir);
+      relDir = relDir || '';
+
+      fs.readdir(dirpath, function(err, current) {
+        if (err) { return self.emit('error', err); }
+        if (!current) { return; }
+
+        try {
+          // append path.sep to directories so they match previous.
+          current = current.map(function(curPath) {
+            if (fs.existsSync(path.join(dir, curPath)) && fs.statSync(path.join(dir, curPath)).isDirectory()) {
+              return curPath + path.sep;
+            } else {
+              return curPath;
+            }
+          });
+        } catch (err) {
+          // race condition-- sometimes the file no longer exists
+        }
+
+        // Get watched files for this dir
+        var previous = self.relative(relDir);
+
+        // If file was deleted
+        previous.filter(function(file) {
+          return current.indexOf(file) < 0;
+        }).forEach(function(file) {
+          if (!helper.isDir(file)) {
+            var filepath = path.join(dir, file);
+            self.remove(filepath);
+            self.emit('deleted', filepath);
+          }
+        });
+
+        // If file was added
+        current.filter(function(file) {
+          return previous.indexOf(file) < 0;
+        }).forEach(function(file) {
+          // Is it a matching pattern?
+          var relFile = path.join(relDir, file);
+          // Add to watch then emit event
+          self._internalAdd(relFile, function() {
+            self.emit('added', path.join(dir, file));
+          });
+        });
+
+      });
+    });
+
+    // Watch for change/rename events on files
+    files.forEach(function(file) {
+      if (helper.isDir(file)) { return; }
+      self._pollFile(file, function(err, filepath) {
+        // Only emit changed if the file still exists
+        // Prevents changed/deleted duplicate events
+        if (fs.existsSync(filepath)) {
+          self.emit('changed', filepath);
+        }
+      });
+    });
+
+    next();
+  }, function() {
+
+    // Return this instance of Gaze
+    // delay before ready solves a lot of issues
+    setTimeout(function() {
+      self.emit('ready', self);
+      if (done) { done.call(self, null, self); }
+    }, delay + 100);
+
+  });
+};
+
+// If an error, handle it here
+Gaze.prototype._handleError = function(err) {
+  if (err.code === 'EMFILE') {
+    return this.emit('error', new Error('EMFILE: Too many opened files.'));
+  }
+  return this.emit('error', err);
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/lib/helper.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/lib/helper.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/lib/helper.js	(revision 533)
@@ -0,0 +1,67 @@
+'use strict';
+
+var path = require('path');
+var helper = module.exports = {};
+
+// Returns boolean whether filepath is dir terminated
+helper.isDir = function isDir(dir) {
+  if (typeof dir !== 'string') { return false; }
+  return (dir.slice(-(path.sep.length)) === path.sep);
+};
+
+// Create a `key:[]` if doesnt exist on `obj` then push or concat the `val`
+helper.objectPush = function objectPush(obj, key, val) {
+  if (obj[key] == null) { obj[key] = []; }
+  if (Array.isArray(val)) { obj[key] = obj[key].concat(val); }
+  else if (val) { obj[key].push(val); }
+  return obj[key] = helper.unique(obj[key]);
+};
+
+// Ensures the dir is marked with path.sep
+helper.markDir = function markDir(dir) {
+  if (typeof dir === 'string' &&
+    dir.slice(-(path.sep.length)) !== path.sep &&
+    dir !== '.') {
+    dir += path.sep;
+  }
+  return dir;
+};
+
+// Changes path.sep to unix ones for testing
+helper.unixifyPathSep = function unixifyPathSep(filepath) {
+  return (process.platform === 'win32') ? String(filepath).replace(/\\/g, '/') : filepath;
+};
+
+/**
+ * Lo-Dash 1.0.1 <http://lodash.com/>
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+ * Available under MIT license <http://lodash.com/license>
+ */
+helper.unique = function unique() { var array = Array.prototype.concat.apply(Array.prototype, arguments); var result = []; for (var i = 0; i < array.length; i++) { if (result.indexOf(array[i]) === -1) { result.push(array[i]); } } return result; };
+
+/**
+ * Copyright (c) 2010 Caolan McMahon
+ * Available under MIT license <https://raw.github.com/caolan/async/master/LICENSE>
+ */
+helper.forEachSeries = function forEachSeries(arr, iterator, callback) {
+  if (!arr.length) { return callback(); }
+  var completed = 0;
+  var iterate = function() {
+    iterator(arr[completed], function (err) {
+      if (err) {
+        callback(err);
+        callback = function() {};
+      } else {
+        completed += 1;
+        if (completed === arr.length) {
+          callback(null);
+        } else {
+          iterate();
+        }
+      }
+    });
+  };
+  iterate();
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.jshintrc
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.jshintrc	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.jshintrc	(revision 533)
@@ -0,0 +1,15 @@
+{
+  "curly": true,
+  "eqeqeq": true,
+  "immed": true,
+  "latedef": true,
+  "newcap": true,
+  "noarg": true,
+  "sub": true,
+  "undef": true,
+  "unused": true,
+  "boss": true,
+  "eqnull": true,
+  "node": true,
+  "es5": true
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+/node_modules/
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.travis.yml
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.travis.yml	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/.travis.yml	(revision 533)
@@ -0,0 +1,6 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
+before_script:
+  - npm install -g grunt-cli
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/Gruntfile.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/Gruntfile.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/Gruntfile.js	(revision 533)
@@ -0,0 +1,48 @@
+'use strict';
+
+module.exports = function(grunt) {
+
+  // Project configuration.
+  grunt.initConfig({
+    nodeunit: {
+      files: ['test/**/*_test.js'],
+    },
+    jshint: {
+      options: {
+        jshintrc: '.jshintrc'
+      },
+      gruntfile: {
+        src: 'Gruntfile.js'
+      },
+      lib: {
+        src: ['lib/**/*.js']
+      },
+      test: {
+        src: ['test/*.js']
+      },
+    },
+    watch: {
+      gruntfile: {
+        files: '<%= jshint.gruntfile.src %>',
+        tasks: ['jshint:gruntfile']
+      },
+      lib: {
+        files: '<%= jshint.lib.src %>',
+        tasks: ['jshint:lib', 'nodeunit']
+      },
+      test: {
+        files: '<%= jshint.test.src %>',
+        tasks: ['jshint:test', 'nodeunit']
+      },
+    },
+  });
+
+  // These plugins provide necessary tasks.
+  grunt.loadNpmTasks('grunt-contrib-nodeunit');
+  grunt.loadNpmTasks('grunt-contrib-jshint');
+  grunt.loadNpmTasks('grunt-contrib-watch');
+
+  // Default task.
+  grunt.registerTask('default', ['jshint', 'nodeunit']);
+
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/LICENSE-MIT
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/LICENSE-MIT	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/LICENSE-MIT	(revision 533)
@@ -0,0 +1,22 @@
+Copyright (c) 2013 "Cowboy" Ben Alman
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/README.md	(revision 533)
@@ -0,0 +1,117 @@
+# globule [![Build Status](https://secure.travis-ci.org/cowboy/node-globule.png?branch=master)](http://travis-ci.org/cowboy/node-globule)
+
+An easy-to-use wildcard globbing library.
+
+## Getting Started
+Install the module with: `npm install globule`
+
+```javascript
+var globule = require('globule');
+var filepaths = globule.find('**/*.js');
+```
+
+## Documentation
+
+### globule.find
+Returns a unique array of all file or directory paths that match the given globbing pattern(s). This method accepts either comma separated globbing patterns or an array of globbing patterns. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.
+
+```js
+globule.find(patterns [, options])
+```
+
+The `options` object supports all [glob][] library options, along with a few extras. These are the most commonly used:
+
+* `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that will be passed the matched `src` filepath and `options` object as arguments. This function should return a `Boolean` value.
+* `nonull` Retain globbing patterns in result set even if they fail to match files.
+* `matchBase` Patterns without slashes will match just the basename part. Eg. this makes `*.js` work like `**/*.js`.
+* `srcBase` Patterns will be matched relative to the specified path instead of the current working directory. This is a synonym for `cwd`.
+* `prefixBase` Any specified `srcBase` will be prefixed to all returned filepaths.
+
+[glob]: https://github.com/isaacs/node-glob
+
+### globule.match
+Match one or more globbing patterns against one or more file paths. Returns a uniqued array of all file paths that match any of the specified globbing patterns. Both the `patterns` and `filepaths` arguments can be a single string or array of strings. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.
+
+```js
+grunt.file.match(patterns, filepaths [, options])
+```
+
+### globule.isMatch
+This method contains the same signature and logic as the `globule.match` method, but returns `true` if any files were matched, otherwise `false`.
+
+```js
+grunt.file.isMatch(patterns, filepaths [, options])
+```
+
+### globule.mapping
+Given a set of source file paths, returns an array of src-dest file mapping objects. Both src and dest paths may be renamed, depending on the options specified.
+
+```js
+globule.mapping(filepaths [, options])
+```
+
+In addition to the options the `globule.find` method supports, the options object also supports these properties:
+
+* `srcBase` The directory from which patterns are matched. Any string specified as `srcBase` is effectively stripped from the beginning of all matched paths.
+* `destBase` The specified path is prefixed to all `dest` filepaths.
+* `ext` Remove anything after (and including) the first `.` in the destination path, then append this value.
+* `extDot` Change the behavior of `ext`, `"first"` and `"last"` will remove anything after the first or last `.` in the destination filename, respectively. Defaults to `"first"`.
+* `flatten` Remove the path component from all matched src files. The src file path is still joined to the specified destBase.
+* `rename` If specified, this function will be responsible for returning the final `dest` filepath. By default, it flattens paths (if specified), changes extensions (if specified) and joins the matched path to the `destBase`.
+
+### globule.findMapping
+This method is a convenience wrapper around the `globule.find` and `globule.mapping` methods.
+
+```js
+globule.findMapping(patterns [, options])
+```
+
+
+## Examples
+
+Given the files `foo/a.js` and `foo/b.js`:
+
+### srcBase and destBase
+
+```js
+globule.find("foo/*.js")
+// ["foo/a.js", "foo/b.js"]
+
+globule.find("*.js", {srcBase: "foo"})
+// ["a.js", "b.js"]
+
+globule.find("*.js", {srcBase: "foo", prefixBase: true})
+// ["foo/a.js", "foo/b.js"]
+```
+
+```js
+globule.findMapping("foo/*.js")
+// [{src: "foo/a.js", dest: "foo/a.js"}, {src: "foo/b.js", dest: "foo/b.js"}]
+
+globule.findMapping("foo/*.js", {destBase: "bar"})
+// [{src: "foo/a.js", dest: "bar/foo/a.js"}, {src: "foo/b.js", dest: "bar/foo/b.js"}]
+
+globule.findMapping("*.js", {srcBase: "foo", destBase: "bar"})
+// [{src: "foo/a.js", dest: "bar/a.js"}, {src: "foo/b.js", dest: "bar/b.js"}]
+```
+
+```js
+globule.mapping(["foo/a.js", "foo/b.js"])
+// [{src: "foo/a.js", dest: "foo/a.js"}, {src: "foo/b.js", dest: "foo/b.js"}]
+
+globule.mapping(["foo/a.js", "foo/b.js"], {destBase: "bar"})
+// [{src: "foo/a.js", dest: "bar/foo/a.js"}, {src: "foo/b.js", dest: "bar/foo/b.js"}]
+
+globule.mapping(["a.js", "b.js"], {srcBase: "foo", destBase: "bar"})
+// [{src: "foo/a.js", dest: "bar/a.js"}, {src: "foo/b.js", dest: "bar/b.js"}]
+```
+
+## Contributing
+In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
+
+## Release History
+_(Nothing yet)_
+
+## License
+Copyright (c) 2013 "Cowboy" Ben Alman  
+Licensed under the MIT license.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/lib/globule.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/lib/globule.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/lib/globule.js	(revision 533)
@@ -0,0 +1,172 @@
+/*
+ * globule
+ * https://github.com/cowboy/node-globule
+ *
+ * Copyright (c) 2013 "Cowboy" Ben Alman
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var _ = require('lodash');
+var glob = require('glob');
+var minimatch = require('minimatch');
+
+// The module.
+var globule = exports;
+
+// Process specified wildcard glob patterns or filenames against a
+// callback, excluding and uniquing files in the result set.
+function processPatterns(patterns, fn) {
+  return _.flatten(patterns).reduce(function(result, pattern) {
+    if (pattern.indexOf('!') === 0) {
+      // If the first character is ! all matches via this pattern should be
+      // removed from the result set.
+      pattern = pattern.slice(1);
+      return _.difference(result, fn(pattern));
+    } else {
+      // Otherwise, add all matching filepaths to the result set.
+      return _.union(result, fn(pattern));
+    }
+  }, []);
+}
+
+// Match a filepath or filepaths against one or more wildcard patterns. Returns
+// all matching filepaths. This behaves just like minimatch.match, but supports
+// any number of patterns.
+globule.match = function(patterns, filepaths, options) {
+  // Return empty set if either patterns or filepaths was omitted.
+  if (patterns == null || filepaths == null) { return []; }
+  // Normalize patterns and filepaths to arrays.
+  if (!_.isArray(patterns)) { patterns = [patterns]; }
+  if (!_.isArray(filepaths)) { filepaths = [filepaths]; }
+  // Return empty set if there are no patterns or filepaths.
+  if (patterns.length === 0 || filepaths.length === 0) { return []; }
+  // Return all matching filepaths.
+  return processPatterns(patterns, function(pattern) {
+    return minimatch.match(filepaths, pattern, options || {});
+  });
+};
+
+// Match a filepath or filepaths against one or more wildcard patterns. Returns
+// true if any of the patterns match.
+globule.isMatch = function() {
+  return globule.match.apply(null, arguments).length > 0;
+};
+
+// Return an array of all file paths that match the given wildcard patterns.
+globule.find = function() {
+  var args = _.toArray(arguments);
+  // If the last argument is an options object, remove it from args.
+  var options = _.isPlainObject(args[args.length - 1]) ? args.pop() : {};
+  // Use the first argument if it's an Array, otherwise use all arguments.
+  var patterns = _.isArray(args[0]) ? args[0] : args;
+  // Return empty set if there are no patterns or filepaths.
+  if (patterns.length === 0) { return []; }
+  var srcBase = options.srcBase || options.cwd;
+  // Create glob-specific options object.
+  var globOptions = _.extend({}, options);
+  if (srcBase) {
+    globOptions.cwd = srcBase;
+  }
+  // Get all matching filepaths.
+  var matches = processPatterns(patterns, function(pattern) {
+    return glob.sync(pattern, globOptions);
+  });
+  // If srcBase and prefixBase were specified, prefix srcBase to matched paths.
+  if (srcBase && options.prefixBase) {
+    matches = matches.map(function(filepath) {
+      return path.join(srcBase, filepath);
+    });
+  }
+  // Filter result set?
+  if (options.filter) {
+    matches = matches.filter(function(filepath) {
+      // If srcBase was specified but prefixBase was NOT, prefix srcBase
+      // temporarily, for filtering.
+      if (srcBase && !options.prefixBase) {
+        filepath = path.join(srcBase, filepath);
+      }
+      try {
+        if (_.isFunction(options.filter)) {
+          return options.filter(filepath, options);
+        } else {
+          // If the file is of the right type and exists, this should work.
+          return fs.statSync(filepath)[options.filter]();
+        }
+      } catch(err) {
+        // Otherwise, it's probably not the right type.
+        return false;
+      }
+    });
+  }
+  return matches;
+};
+
+var pathSeparatorRe = /[\/\\]/g;
+var extDotRe = {
+  first: /(\.[^\/]*)?$/,
+  last: /(\.[^\/\.]*)?$/,
+};
+function rename(dest, options) {
+  // Flatten path?
+  if (options.flatten) {
+    dest = path.basename(dest);
+  }
+  // Change the extension?
+  if (options.ext) {
+    dest = dest.replace(extDotRe[options.extDot], options.ext);
+  }
+  // Join dest and destBase?
+  if (options.destBase) {
+    dest = path.join(options.destBase, dest);
+  }
+  return dest;
+}
+
+// Build a mapping of src-dest filepaths from the given set of filepaths.
+globule.mapping = function(filepaths, options) {
+  // Return empty set if filepaths was omitted.
+  if (filepaths == null) { return []; }
+  options = _.defaults({}, options, {
+    extDot: 'first',
+    rename: rename,
+  });
+  var files = [];
+  var fileByDest = {};
+  // Find all files matching pattern, using passed-in options.
+  filepaths.forEach(function(src) {
+    // Generate destination filename.
+    var dest = options.rename(src, options);
+    // Prepend srcBase to all src paths.
+    if (options.srcBase) {
+      src = path.join(options.srcBase, src);
+    }
+    // Normalize filepaths to be unix-style.
+    dest = dest.replace(pathSeparatorRe, '/');
+    src = src.replace(pathSeparatorRe, '/');
+    // Map correct src path to dest path.
+    if (fileByDest[dest]) {
+      // If dest already exists, push this src onto that dest's src array.
+      fileByDest[dest].src.push(src);
+    } else {
+      // Otherwise create a new src-dest file mapping object.
+      files.push({
+        src: [src],
+        dest: dest,
+      });
+      // And store a reference for later use.
+      fileByDest[dest] = files[files.length - 1];
+    }
+  });
+  return files;
+};
+
+// Return a mapping of src-dest filepaths from files matching the given
+// wildcard patterns.
+globule.findMapping = function(patterns, options) {
+  return globule.mapping(globule.find(patterns, options), options);
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/.bin/lodash
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/.bin/lodash	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/.bin/lodash	(revision 533)
@@ -0,0 +1,1 @@
+link ../lodash/build.js
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/.npmignore	(revision 533)
@@ -0,0 +1,2 @@
+.*.swp
+test/a/
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/.travis.yml
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/.travis.yml	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/.travis.yml	(revision 533)
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+  - 0.8
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/LICENSE	(revision 533)
@@ -0,0 +1,27 @@
+Copyright (c) Isaac Z. Schlueter ("Author")
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/README.md	(revision 533)
@@ -0,0 +1,233 @@
+# Glob
+
+This is a glob implementation in JavaScript.  It uses the `minimatch`
+library to do its matching.
+
+## Attention: node-glob users!
+
+The API has changed dramatically between 2.x and 3.x. This library is
+now 100% JavaScript, and the integer flags have been replaced with an
+options object.
+
+Also, there's an event emitter class, proper tests, and all the other
+things you've come to expect from node modules.
+
+And best of all, no compilation!
+
+## Usage
+
+```javascript
+var glob = require("glob")
+
+// options is optional
+glob("**/*.js", options, function (er, files) {
+  // files is an array of filenames.
+  // If the `nonull` option is set, and nothing
+  // was found, then files is ["**/*.js"]
+  // er is an error object or null.
+})
+```
+
+## Features
+
+Please see the [minimatch
+documentation](https://github.com/isaacs/minimatch) for more details.
+
+Supports these glob features:
+
+* Brace Expansion
+* Extended glob matching
+* "Globstar" `**` matching
+
+See:
+
+* `man sh`
+* `man bash`
+* `man 3 fnmatch`
+* `man 5 gitignore`
+* [minimatch documentation](https://github.com/isaacs/minimatch)
+
+## glob(pattern, [options], cb)
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* `cb` {Function}
+  * `err` {Error | null}
+  * `matches` {Array<String>} filenames found matching the pattern
+
+Perform an asynchronous glob search.
+
+## glob.sync(pattern, [options]
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* return: {Array<String>} filenames found matching the pattern
+
+Perform a synchronous glob search.
+
+## Class: glob.Glob
+
+Create a Glob object by instanting the `glob.Glob` class.
+
+```javascript
+var Glob = require("glob").Glob
+var mg = new Glob(pattern, options, cb)
+```
+
+It's an EventEmitter, and starts walking the filesystem to find matches
+immediately.
+
+### new glob.Glob(pattern, [options], [cb])
+
+* `pattern` {String} pattern to search for
+* `options` {Object}
+* `cb` {Function} Called when an error occurs, or matches are found
+  * `err` {Error | null}
+  * `matches` {Array<String>} filenames found matching the pattern
+
+Note that if the `sync` flag is set in the options, then matches will
+be immediately available on the `g.found` member.
+
+### Properties
+
+* `minimatch` The minimatch object that the glob uses.
+* `options` The options object passed in.
+* `error` The error encountered.  When an error is encountered, the
+  glob object is in an undefined state, and should be discarded.
+* `aborted` Boolean which is set to true when calling `abort()`.  There
+  is no way at this time to continue a glob search after aborting, but
+  you can re-use the statCache to avoid having to duplicate syscalls.
+
+### Events
+
+* `end` When the matching is finished, this is emitted with all the
+  matches found.  If the `nonull` option is set, and no match was found,
+  then the `matches` list contains the original pattern.  The matches
+  are sorted, unless the `nosort` flag is set.
+* `match` Every time a match is found, this is emitted with the matched.
+* `error` Emitted when an unexpected error is encountered, or whenever
+  any fs error occurs if `options.strict` is set.
+* `abort` When `abort()` is called, this event is raised.
+
+### Methods
+
+* `abort` Stop the search.
+
+### Options
+
+All the options that can be passed to Minimatch can also be passed to
+Glob to change pattern matching behavior.  Also, some have been added,
+or have glob-specific ramifications.
+
+All options are false by default, unless otherwise noted.
+
+All options are added to the glob object, as well.
+
+* `cwd` The current working directory in which to search.  Defaults
+  to `process.cwd()`.
+* `root` The place where patterns starting with `/` will be mounted
+  onto.  Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
+  systems, and `C:\` or some such on Windows.)
+* `nomount` By default, a pattern starting with a forward-slash will be
+  "mounted" onto the root setting, so that a valid filesystem path is
+  returned.  Set this flag to disable that behavior.
+* `mark` Add a `/` character to directory matches.  Note that this
+  requires additional stat calls.
+* `nosort` Don't sort the results.
+* `stat` Set to true to stat *all* results.  This reduces performance
+  somewhat, and is completely unnecessary, unless `readdir` is presumed
+  to be an untrustworthy indicator of file existence.  It will cause
+  ELOOP to be triggered one level sooner in the case of cyclical
+  symbolic links.
+* `silent` When an unusual error is encountered
+  when attempting to read a directory, a warning will be printed to
+  stderr.  Set the `silent` option to true to suppress these warnings.
+* `strict` When an unusual error is encountered
+  when attempting to read a directory, the process will just continue on
+  in search of other matches.  Set the `strict` option to raise an error
+  in these cases.
+* `statCache` A cache of results of filesystem information, to prevent
+  unnecessary stat calls.  While it should not normally be necessary to
+  set this, you may pass the statCache from one glob() call to the
+  options object of another, if you know that the filesystem will not
+  change between calls.  (See "Race Conditions" below.)
+* `sync` Perform a synchronous glob search.
+* `nounique` In some cases, brace-expanded patterns can result in the
+  same file showing up multiple times in the result set.  By default,
+  this implementation prevents duplicates in the result set.
+  Set this flag to disable that behavior.
+* `nonull` Set to never return an empty set, instead returning a set
+  containing the pattern itself.  This is the default in glob(3).
+* `nocase` Perform a case-insensitive match.  Note that case-insensitive
+  filesystems will sometimes result in glob returning results that are
+  case-insensitively matched anyway, since readdir and stat will not
+  raise an error.
+* `debug` Set to enable debug logging in minimatch and glob.
+* `globDebug` Set to enable debug logging in glob, but not minimatch.
+
+## Comparisons to other fnmatch/glob implementations
+
+While strict compliance with the existing standards is a worthwhile
+goal, some discrepancies exist between node-glob and other
+implementations, and are intentional.
+
+If the pattern starts with a `!` character, then it is negated.  Set the
+`nonegate` flag to suppress this behavior, and treat leading `!`
+characters normally.  This is perhaps relevant if you wish to start the
+pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
+characters at the start of a pattern will negate the pattern multiple
+times.
+
+If a pattern starts with `#`, then it is treated as a comment, and
+will not match anything.  Use `\#` to match a literal `#` at the
+start of a line, or set the `nocomment` flag to suppress this behavior.
+
+The double-star character `**` is supported by default, unless the
+`noglobstar` flag is set.  This is supported in the manner of bsdglob
+and bash 4.1, where `**` only has special significance if it is the only
+thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
+`a/**b` will not.  **Note that this is different from the way that `**` is
+handled by ruby's `Dir` class.**
+
+If an escaped pattern has no matches, and the `nonull` flag is set,
+then glob returns the pattern as-provided, rather than
+interpreting the character escapes.  For example,
+`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
+`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
+that it does not resolve escaped pattern characters.
+
+If brace expansion is not disabled, then it is performed before any
+other interpretation of the glob pattern.  Thus, a pattern like
+`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
+**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
+checked for validity.  Since those two are valid, matching proceeds.
+
+## Windows
+
+**Please only use forward-slashes in glob expressions.**
+
+Though windows uses either `/` or `\` as its path separator, only `/`
+characters are used by this glob implementation.  You must use
+forward-slashes **only** in glob expressions.  Back-slashes will always
+be interpreted as escape characters, not path separators.
+
+Results from absolute patterns such as `/foo/*` are mounted onto the
+root setting using `path.join`.  On windows, this will by default result
+in `/foo/*` matching `C:\foo\bar.txt`.
+
+## Race Conditions
+
+Glob searching, by its very nature, is susceptible to race conditions,
+since it relies on directory walking and such.
+
+As a result, it is possible that a file that exists when glob looks for
+it may have been deleted or modified by the time it returns the result.
+
+As part of its internal implementation, this program caches all stat
+and readdir calls that it makes, in order to cut down on system
+overhead.  However, this also makes it even more susceptible to races,
+especially if the statCache object is reused between glob calls.
+
+Users are thus advised not to use a glob result as a
+guarantee of filesystem state in the face of rapid changes.
+For the vast majority of operations, this is never a problem.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/examples/g.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/examples/g.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/examples/g.js	(revision 533)
@@ -0,0 +1,9 @@
+var Glob = require("../").Glob
+
+var pattern = "test/a/**/[cg]/../[cg]"
+console.log(pattern)
+
+var mg = new Glob(pattern, {mark: true, sync:true}, function (er, matches) {
+  console.log("matches", matches)
+})
+console.log("after")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/examples/usr-local.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/examples/usr-local.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/examples/usr-local.js	(revision 533)
@@ -0,0 +1,9 @@
+var Glob = require("../").Glob
+
+var pattern = "{./*/*,/*,/usr/local/*}"
+console.log(pattern)
+
+var mg = new Glob(pattern, {mark: true}, function (er, matches) {
+  console.log("matches", matches)
+})
+console.log("after")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/glob.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/glob.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/glob.js	(revision 533)
@@ -0,0 +1,643 @@
+// Approach:
+//
+// 1. Get the minimatch set
+// 2. For each pattern in the set, PROCESS(pattern)
+// 3. Store matches per-set, then uniq them
+//
+// PROCESS(pattern)
+// Get the first [n] items from pattern that are all strings
+// Join these together.  This is PREFIX.
+//   If there is no more remaining, then stat(PREFIX) and
+//   add to matches if it succeeds.  END.
+// readdir(PREFIX) as ENTRIES
+//   If fails, END
+//   If pattern[n] is GLOBSTAR
+//     // handle the case where the globstar match is empty
+//     // by pruning it out, and testing the resulting pattern
+//     PROCESS(pattern[0..n] + pattern[n+1 .. $])
+//     // handle other cases.
+//     for ENTRY in ENTRIES (not dotfiles)
+//       // attach globstar + tail onto the entry
+//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $])
+//
+//   else // not globstar
+//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
+//       Test ENTRY against pattern[n]
+//       If fails, continue
+//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
+//
+// Caveat:
+//   Cache all stats and readdirs results to minimize syscall.  Since all
+//   we ever care about is existence and directory-ness, we can just keep
+//   `true` for files, and [children,...] for directories, or `false` for
+//   things that don't exist.
+
+
+
+module.exports = glob
+
+var fs = require("graceful-fs")
+, minimatch = require("minimatch")
+, Minimatch = minimatch.Minimatch
+, inherits = require("inherits")
+, EE = require("events").EventEmitter
+, path = require("path")
+, isDir = {}
+, assert = require("assert").ok
+
+function glob (pattern, options, cb) {
+  if (typeof options === "function") cb = options, options = {}
+  if (!options) options = {}
+
+  if (typeof options === "number") {
+    deprecated()
+    return
+  }
+
+  var g = new Glob(pattern, options, cb)
+  return g.sync ? g.found : g
+}
+
+glob.fnmatch = deprecated
+
+function deprecated () {
+  throw new Error("glob's interface has changed. Please see the docs.")
+}
+
+glob.sync = globSync
+function globSync (pattern, options) {
+  if (typeof options === "number") {
+    deprecated()
+    return
+  }
+
+  options = options || {}
+  options.sync = true
+  return glob(pattern, options)
+}
+
+
+glob.Glob = Glob
+inherits(Glob, EE)
+function Glob (pattern, options, cb) {
+  if (!(this instanceof Glob)) {
+    return new Glob(pattern, options, cb)
+  }
+
+  if (typeof cb === "function") {
+    this.on("error", cb)
+    this.on("end", function (matches) {
+      cb(null, matches)
+    })
+  }
+
+  options = options || {}
+
+  this.EOF = {}
+  this._emitQueue = []
+
+  this.maxDepth = options.maxDepth || 1000
+  this.maxLength = options.maxLength || Infinity
+  this.statCache = options.statCache || {}
+
+  this.changedCwd = false
+  var cwd = process.cwd()
+  if (!options.hasOwnProperty("cwd")) this.cwd = cwd
+  else {
+    this.cwd = options.cwd
+    this.changedCwd = path.resolve(options.cwd) !== cwd
+  }
+
+  this.root = options.root || path.resolve(this.cwd, "/")
+  this.root = path.resolve(this.root)
+  if (process.platform === "win32")
+    this.root = this.root.replace(/\\/g, "/")
+
+  this.nomount = !!options.nomount
+
+  if (!pattern) {
+    throw new Error("must provide pattern")
+  }
+
+  // base-matching: just use globstar for that.
+  if (options.matchBase && -1 === pattern.indexOf("/")) {
+    if (options.noglobstar) {
+      throw new Error("base matching requires globstar")
+    }
+    pattern = "**/" + pattern
+  }
+
+  this.strict = options.strict !== false
+  this.dot = !!options.dot
+  this.mark = !!options.mark
+  this.sync = !!options.sync
+  this.nounique = !!options.nounique
+  this.nonull = !!options.nonull
+  this.nosort = !!options.nosort
+  this.nocase = !!options.nocase
+  this.stat = !!options.stat
+
+  this.debug = !!options.debug || !!options.globDebug
+  if (this.debug)
+    this.log = console.error
+
+  this.silent = !!options.silent
+
+  var mm = this.minimatch = new Minimatch(pattern, options)
+  this.options = mm.options
+  pattern = this.pattern = mm.pattern
+
+  this.error = null
+  this.aborted = false
+
+  EE.call(this)
+
+  // process each pattern in the minimatch set
+  var n = this.minimatch.set.length
+
+  // The matches are stored as {<filename>: true,...} so that
+  // duplicates are automagically pruned.
+  // Later, we do an Object.keys() on these.
+  // Keep them as a list so we can fill in when nonull is set.
+  this.matches = new Array(n)
+
+  this.minimatch.set.forEach(iterator.bind(this))
+  function iterator (pattern, i, set) {
+    this._process(pattern, 0, i, function (er) {
+      if (er) this.emit("error", er)
+      if (-- n <= 0) this._finish()
+    })
+  }
+}
+
+Glob.prototype.log = function () {}
+
+Glob.prototype._finish = function () {
+  assert(this instanceof Glob)
+
+  var nou = this.nounique
+  , all = nou ? [] : {}
+
+  for (var i = 0, l = this.matches.length; i < l; i ++) {
+    var matches = this.matches[i]
+    this.log("matches[%d] =", i, matches)
+    // do like the shell, and spit out the literal glob
+    if (!matches) {
+      if (this.nonull) {
+        var literal = this.minimatch.globSet[i]
+        if (nou) all.push(literal)
+        else all[literal] = true
+      }
+    } else {
+      // had matches
+      var m = Object.keys(matches)
+      if (nou) all.push.apply(all, m)
+      else m.forEach(function (m) {
+        all[m] = true
+      })
+    }
+  }
+
+  if (!nou) all = Object.keys(all)
+
+  if (!this.nosort) {
+    all = all.sort(this.nocase ? alphasorti : alphasort)
+  }
+
+  if (this.mark) {
+    // at *some* point we statted all of these
+    all = all.map(function (m) {
+      var sc = this.statCache[m]
+      if (!sc)
+        return m
+      var isDir = (Array.isArray(sc) || sc === 2)
+      if (isDir && m.slice(-1) !== "/") {
+        return m + "/"
+      }
+      if (!isDir && m.slice(-1) === "/") {
+        return m.replace(/\/+$/, "")
+      }
+      return m
+    }, this)
+  }
+
+  this.log("emitting end", all)
+
+  this.EOF = this.found = all
+  this.emitMatch(this.EOF)
+}
+
+function alphasorti (a, b) {
+  a = a.toLowerCase()
+  b = b.toLowerCase()
+  return alphasort(a, b)
+}
+
+function alphasort (a, b) {
+  return a > b ? 1 : a < b ? -1 : 0
+}
+
+Glob.prototype.abort = function () {
+  this.aborted = true
+  this.emit("abort")
+}
+
+Glob.prototype.pause = function () {
+  if (this.paused) return
+  if (this.sync)
+    this.emit("error", new Error("Can't pause/resume sync glob"))
+  this.paused = true
+  this.emit("pause")
+}
+
+Glob.prototype.resume = function () {
+  if (!this.paused) return
+  if (this.sync)
+    this.emit("error", new Error("Can't pause/resume sync glob"))
+  this.paused = false
+  this.emit("resume")
+  this._processEmitQueue()
+  //process.nextTick(this.emit.bind(this, "resume"))
+}
+
+Glob.prototype.emitMatch = function (m) {
+  this._emitQueue.push(m)
+  this._processEmitQueue()
+}
+
+Glob.prototype._processEmitQueue = function (m) {
+  while (!this._processingEmitQueue &&
+         !this.paused) {
+    this._processingEmitQueue = true
+    var m = this._emitQueue.shift()
+    if (!m) {
+      this._processingEmitQueue = false
+      break
+    }
+
+    this.log('emit!', m === this.EOF ? "end" : "match")
+
+    this.emit(m === this.EOF ? "end" : "match", m)
+    this._processingEmitQueue = false
+  }
+}
+
+Glob.prototype._process = function (pattern, depth, index, cb_) {
+  assert(this instanceof Glob)
+
+  var cb = function cb (er, res) {
+    assert(this instanceof Glob)
+    if (this.paused) {
+      if (!this._processQueue) {
+        this._processQueue = []
+        this.once("resume", function () {
+          var q = this._processQueue
+          this._processQueue = null
+          q.forEach(function (cb) { cb() })
+        })
+      }
+      this._processQueue.push(cb_.bind(this, er, res))
+    } else {
+      cb_.call(this, er, res)
+    }
+  }.bind(this)
+
+  if (this.aborted) return cb()
+
+  if (depth > this.maxDepth) return cb()
+
+  // Get the first [n] parts of pattern that are all strings.
+  var n = 0
+  while (typeof pattern[n] === "string") {
+    n ++
+  }
+  // now n is the index of the first one that is *not* a string.
+
+  // see if there's anything else
+  var prefix
+  switch (n) {
+    // if not, then this is rather simple
+    case pattern.length:
+      prefix = pattern.join("/")
+      this._stat(prefix, function (exists, isDir) {
+        // either it's there, or it isn't.
+        // nothing more to do, either way.
+        if (exists) {
+          if (prefix && isAbsolute(prefix) && !this.nomount) {
+	    if (prefix.charAt(0) === "/") {
+              prefix = path.join(this.root, prefix)
+	    } else {
+	      prefix = path.resolve(this.root, prefix)
+	    }
+          }
+
+          if (process.platform === "win32")
+            prefix = prefix.replace(/\\/g, "/")
+
+          this.matches[index] = this.matches[index] || {}
+          this.matches[index][prefix] = true
+          this.emitMatch(prefix)
+        }
+        return cb()
+      })
+      return
+
+    case 0:
+      // pattern *starts* with some non-trivial item.
+      // going to readdir(cwd), but not include the prefix in matches.
+      prefix = null
+      break
+
+    default:
+      // pattern has some string bits in the front.
+      // whatever it starts with, whether that's "absolute" like /foo/bar,
+      // or "relative" like "../baz"
+      prefix = pattern.slice(0, n)
+      prefix = prefix.join("/")
+      break
+  }
+
+  // get the list of entries.
+  var read
+  if (prefix === null) read = "."
+  else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {
+    if (!prefix || !isAbsolute(prefix)) {
+      prefix = path.join("/", prefix)
+    }
+    read = prefix = path.resolve(prefix)
+
+    // if (process.platform === "win32")
+    //   read = prefix = prefix.replace(/^[a-zA-Z]:|\\/g, "/")
+
+    this.log('absolute: ', prefix, this.root, pattern, read)
+  } else {
+    read = prefix
+  }
+
+  this.log('readdir(%j)', read, this.cwd, this.root)
+
+  return this._readdir(read, function (er, entries) {
+    if (er) {
+      // not a directory!
+      // this means that, whatever else comes after this, it can never match
+      return cb()
+    }
+
+    // globstar is special
+    if (pattern[n] === minimatch.GLOBSTAR) {
+      // test without the globstar, and with every child both below
+      // and replacing the globstar.
+      var s = [ pattern.slice(0, n).concat(pattern.slice(n + 1)) ]
+      entries.forEach(function (e) {
+        if (e.charAt(0) === "." && !this.dot) return
+        // instead of the globstar
+        s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1)))
+        // below the globstar
+        s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n)))
+      }, this)
+
+      // now asyncForEach over this
+      var l = s.length
+      , errState = null
+      s.forEach(function (gsPattern) {
+        this._process(gsPattern, depth + 1, index, function (er) {
+          if (errState) return
+          if (er) return cb(errState = er)
+          if (--l <= 0) return cb()
+        })
+      }, this)
+
+      return
+    }
+
+    // not a globstar
+    // It will only match dot entries if it starts with a dot, or if
+    // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
+    var pn = pattern[n]
+    if (typeof pn === "string") {
+      var found = entries.indexOf(pn) !== -1
+      entries = found ? entries[pn] : []
+    } else {
+      var rawGlob = pattern[n]._glob
+      , dotOk = this.dot || rawGlob.charAt(0) === "."
+
+      entries = entries.filter(function (e) {
+        return (e.charAt(0) !== "." || dotOk) &&
+               (typeof pattern[n] === "string" && e === pattern[n] ||
+                e.match(pattern[n]))
+      })
+    }
+
+    // If n === pattern.length - 1, then there's no need for the extra stat
+    // *unless* the user has specified "mark" or "stat" explicitly.
+    // We know that they exist, since the readdir returned them.
+    if (n === pattern.length - 1 &&
+        !this.mark &&
+        !this.stat) {
+      entries.forEach(function (e) {
+        if (prefix) {
+          if (prefix !== "/") e = prefix + "/" + e
+          else e = prefix + e
+        }
+        if (e.charAt(0) === "/" && !this.nomount) {
+          e = path.join(this.root, e)
+        }
+
+        if (process.platform === "win32")
+          e = e.replace(/\\/g, "/")
+
+        this.matches[index] = this.matches[index] || {}
+        this.matches[index][e] = true
+        this.emitMatch(e)
+      }, this)
+      return cb.call(this)
+    }
+
+
+    // now test all the remaining entries as stand-ins for that part
+    // of the pattern.
+    var l = entries.length
+    , errState = null
+    if (l === 0) return cb() // no matches possible
+    entries.forEach(function (e) {
+      var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))
+      this._process(p, depth + 1, index, function (er) {
+        if (errState) return
+        if (er) return cb(errState = er)
+        if (--l === 0) return cb.call(this)
+      })
+    }, this)
+  })
+
+}
+
+Glob.prototype._stat = function (f, cb) {
+  assert(this instanceof Glob)
+  var abs = f
+  if (f.charAt(0) === "/") {
+    abs = path.join(this.root, f)
+  } else if (this.changedCwd) {
+    abs = path.resolve(this.cwd, f)
+  }
+  this.log('stat', [this.cwd, f, '=', abs])
+  if (f.length > this.maxLength) {
+    var er = new Error("Path name too long")
+    er.code = "ENAMETOOLONG"
+    er.path = f
+    return this._afterStat(f, abs, cb, er)
+  }
+
+  if (this.statCache.hasOwnProperty(f)) {
+    var exists = this.statCache[f]
+    , isDir = exists && (Array.isArray(exists) || exists === 2)
+    if (this.sync) return cb.call(this, !!exists, isDir)
+    return process.nextTick(cb.bind(this, !!exists, isDir))
+  }
+
+  if (this.sync) {
+    var er, stat
+    try {
+      stat = fs.statSync(abs)
+    } catch (e) {
+      er = e
+    }
+    this._afterStat(f, abs, cb, er, stat)
+  } else {
+    fs.stat(abs, this._afterStat.bind(this, f, abs, cb))
+  }
+}
+
+Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
+  var exists
+  assert(this instanceof Glob)
+
+  if (abs.slice(-1) === "/" && stat && !stat.isDirectory()) {
+    this.log("should be ENOTDIR, fake it")
+
+    er = new Error("ENOTDIR, not a directory '" + abs + "'")
+    er.path = abs
+    er.code = "ENOTDIR"
+    stat = null
+  }
+
+  if (er || !stat) {
+    exists = false
+  } else {
+    exists = stat.isDirectory() ? 2 : 1
+  }
+  this.statCache[f] = this.statCache[f] || exists
+  cb.call(this, !!exists, exists === 2)
+}
+
+Glob.prototype._readdir = function (f, cb) {
+  assert(this instanceof Glob)
+  var abs = f
+  if (f.charAt(0) === "/") {
+    abs = path.join(this.root, f)
+  } else if (isAbsolute(f)) {
+    abs = f
+  } else if (this.changedCwd) {
+    abs = path.resolve(this.cwd, f)
+  }
+
+  this.log('readdir', [this.cwd, f, abs])
+  if (f.length > this.maxLength) {
+    var er = new Error("Path name too long")
+    er.code = "ENAMETOOLONG"
+    er.path = f
+    return this._afterReaddir(f, abs, cb, er)
+  }
+
+  if (this.statCache.hasOwnProperty(f)) {
+    var c = this.statCache[f]
+    if (Array.isArray(c)) {
+      if (this.sync) return cb.call(this, null, c)
+      return process.nextTick(cb.bind(this, null, c))
+    }
+
+    if (!c || c === 1) {
+      // either ENOENT or ENOTDIR
+      var code = c ? "ENOTDIR" : "ENOENT"
+      , er = new Error((c ? "Not a directory" : "Not found") + ": " + f)
+      er.path = f
+      er.code = code
+      this.log(f, er)
+      if (this.sync) return cb.call(this, er)
+      return process.nextTick(cb.bind(this, er))
+    }
+
+    // at this point, c === 2, meaning it's a dir, but we haven't
+    // had to read it yet, or c === true, meaning it's *something*
+    // but we don't have any idea what.  Need to read it, either way.
+  }
+
+  if (this.sync) {
+    var er, entries
+    try {
+      entries = fs.readdirSync(abs)
+    } catch (e) {
+      er = e
+    }
+    return this._afterReaddir(f, abs, cb, er, entries)
+  }
+
+  fs.readdir(abs, this._afterReaddir.bind(this, f, abs, cb))
+}
+
+Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) {
+  assert(this instanceof Glob)
+  if (entries && !er) {
+    this.statCache[f] = entries
+    // if we haven't asked to stat everything for suresies, then just
+    // assume that everything in there exists, so we can avoid
+    // having to stat it a second time.  This also gets us one step
+    // further into ELOOP territory.
+    if (!this.mark && !this.stat) {
+      entries.forEach(function (e) {
+        if (f === "/") e = f + e
+        else e = f + "/" + e
+        this.statCache[e] = true
+      }, this)
+    }
+
+    return cb.call(this, er, entries)
+  }
+
+  // now handle errors, and cache the information
+  if (er) switch (er.code) {
+    case "ENOTDIR": // totally normal. means it *does* exist.
+      this.statCache[f] = 1
+      return cb.call(this, er)
+    case "ENOENT": // not terribly unusual
+    case "ELOOP":
+    case "ENAMETOOLONG":
+    case "UNKNOWN":
+      this.statCache[f] = false
+      return cb.call(this, er)
+    default: // some unusual error.  Treat as failure.
+      this.statCache[f] = false
+      if (this.strict) this.emit("error", er)
+      if (!this.silent) console.error("glob error", er)
+      return cb.call(this, er)
+  }
+}
+
+var isAbsolute = process.platform === "win32" ? absWin : absUnix
+
+function absWin (p) {
+  if (absUnix(p)) return true
+  // pull off the device/UNC bit from a windows path.
+  // from node's lib/path.js
+  var splitDeviceRe =
+      /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/
+    , result = splitDeviceRe.exec(p)
+    , device = result[1] || ''
+    , isUnc = device && device.charAt(1) !== ':'
+    , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
+
+  return isAbsolute
+}
+
+function absUnix (p) {
+  return p.charAt(0) === "/" || p === ""
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+node_modules/
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/LICENSE	(revision 533)
@@ -0,0 +1,27 @@
+Copyright (c) Isaac Z. Schlueter ("Author")
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/README.md	(revision 533)
@@ -0,0 +1,33 @@
+# graceful-fs
+
+graceful-fs functions as a drop-in replacement for the fs module,
+making various improvements.
+
+The improvements are meant to normalize behavior across different
+platforms and environments, and to make filesystem access more
+resilient to errors.
+
+## Improvements over fs module
+
+graceful-fs:
+
+* keeps track of how many file descriptors are open, and by default
+  limits this to 1024. Any further requests to open a file are put in a
+  queue until new slots become available. If 1024 turns out to be too
+  much, it decreases the limit further.
+* fixes `lchmod` for Node versions prior to 0.6.2.
+* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
+* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
+  `lchown` if the user isn't root.
+* makes `lchmod` and `lchown` become noops, if not available.
+* retries reading a file if `read` results in EAGAIN error.
+
+On Windows, it retries renaming a file for up to one second if `EACCESS`
+or `EPERM` error occurs, likely because antivirus software has locked
+the directory.
+
+## Configuration
+
+The maximum number of open file descriptors that graceful-fs manages may
+be adjusted by setting `fs.MAX_OPEN` to a different number. The default
+is 1024.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/graceful-fs.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/graceful-fs.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/graceful-fs.js	(revision 533)
@@ -0,0 +1,442 @@
+// this keeps a queue of opened file descriptors, and will make
+// fs operations wait until some have closed before trying to open more.
+
+var fs = exports = module.exports = {}
+fs._originalFs = require("fs")
+
+Object.getOwnPropertyNames(fs._originalFs).forEach(function(prop) {
+  var desc = Object.getOwnPropertyDescriptor(fs._originalFs, prop)
+  Object.defineProperty(fs, prop, desc)
+})
+
+var queue = []
+  , constants = require("constants")
+
+fs._curOpen = 0
+
+fs.MIN_MAX_OPEN = 64
+fs.MAX_OPEN = 1024
+
+// prevent EMFILE errors
+function OpenReq (path, flags, mode, cb) {
+  this.path = path
+  this.flags = flags
+  this.mode = mode
+  this.cb = cb
+}
+
+function noop () {}
+
+fs.open = gracefulOpen
+
+function gracefulOpen (path, flags, mode, cb) {
+  if (typeof mode === "function") cb = mode, mode = null
+  if (typeof cb !== "function") cb = noop
+
+  if (fs._curOpen >= fs.MAX_OPEN) {
+    queue.push(new OpenReq(path, flags, mode, cb))
+    setTimeout(flush)
+    return
+  }
+  open(path, flags, mode, function (er, fd) {
+    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
+      // that was too many.  reduce max, get back in queue.
+      // this should only happen once in a great while, and only
+      // if the ulimit -n is set lower than 1024.
+      fs.MAX_OPEN = fs._curOpen - 1
+      return fs.open(path, flags, mode, cb)
+    }
+    cb(er, fd)
+  })
+}
+
+function open (path, flags, mode, cb) {
+  cb = cb || noop
+  fs._curOpen ++
+  fs._originalFs.open.call(fs, path, flags, mode, function (er, fd) {
+    if (er) onclose()
+    cb(er, fd)
+  })
+}
+
+fs.openSync = function (path, flags, mode) {
+  var ret
+  ret = fs._originalFs.openSync.call(fs, path, flags, mode)
+  fs._curOpen ++
+  return ret
+}
+
+function onclose () {
+  fs._curOpen --
+  flush()
+}
+
+function flush () {
+  while (fs._curOpen < fs.MAX_OPEN) {
+    var req = queue.shift()
+    if (!req) return
+    switch (req.constructor.name) {
+      case 'OpenReq':
+        open(req.path, req.flags || "r", req.mode || 0777, req.cb)
+        break
+      case 'ReaddirReq':
+        readdir(req.path, req.cb)
+        break
+      case 'ReadFileReq':
+        readFile(req.path, req.options, req.cb)
+        break
+      case 'WriteFileReq':
+        writeFile(req.path, req.data, req.options, req.cb)
+        break
+      default:
+        throw new Error('Unknown req type: ' + req.constructor.name)
+    }
+  }
+}
+
+fs.close = function (fd, cb) {
+  cb = cb || noop
+  fs._originalFs.close.call(fs, fd, function (er) {
+    onclose()
+    cb(er)
+  })
+}
+
+fs.closeSync = function (fd) {
+  try {
+    return fs._originalFs.closeSync.call(fs, fd)
+  } finally {
+    onclose()
+  }
+}
+
+
+// readdir takes a fd as well.
+// however, the sync version closes it right away, so
+// there's no need to wrap.
+// It would be nice to catch when it throws an EMFILE,
+// but that's relatively rare anyway.
+
+fs.readdir = gracefulReaddir
+
+function gracefulReaddir (path, cb) {
+  if (fs._curOpen >= fs.MAX_OPEN) {
+    queue.push(new ReaddirReq(path, cb))
+    setTimeout(flush)
+    return
+  }
+
+  readdir(path, function (er, files) {
+    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
+      fs.MAX_OPEN = fs._curOpen - 1
+      return fs.readdir(path, cb)
+    }
+    cb(er, files)
+  })
+}
+
+function readdir (path, cb) {
+  cb = cb || noop
+  fs._curOpen ++
+  fs._originalFs.readdir.call(fs, path, function (er, files) {
+    onclose()
+    cb(er, files)
+  })
+}
+
+function ReaddirReq (path, cb) {
+  this.path = path
+  this.cb = cb
+}
+
+
+fs.readFile = gracefulReadFile
+
+function gracefulReadFile(path, options, cb) {
+  if (typeof options === "function") cb = options, options = null
+  if (typeof cb !== "function") cb = noop
+
+  if (fs._curOpen >= fs.MAX_OPEN) {
+    queue.push(new ReadFileReq(path, options, cb))
+    setTimeout(flush)
+    return
+  }
+
+  readFile(path, options, function (er, data) {
+    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
+      fs.MAX_OPEN = fs._curOpen - 1
+      return fs.readFile(path, options, cb)
+    }
+    cb(er, data)
+  })
+}
+
+function readFile (path, options, cb) {
+  cb = cb || noop
+  fs._curOpen ++
+  fs._originalFs.readFile.call(fs, path, options, function (er, data) {
+    onclose()
+    cb(er, data)
+  })
+}
+
+function ReadFileReq (path, options, cb) {
+  this.path = path
+  this.options = options
+  this.cb = cb
+}
+
+
+
+
+fs.writeFile = gracefulWriteFile
+
+function gracefulWriteFile(path, data, options, cb) {
+  if (typeof options === "function") cb = options, options = null
+  if (typeof cb !== "function") cb = noop
+
+  if (fs._curOpen >= fs.MAX_OPEN) {
+    queue.push(new WriteFileReq(path, data, options, cb))
+    setTimeout(flush)
+    return
+  }
+
+  writeFile(path, data, options, function (er) {
+    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
+      fs.MAX_OPEN = fs._curOpen - 1
+      return fs.writeFile(path, data, options, cb)
+    }
+    cb(er)
+  })
+}
+
+function writeFile (path, data, options, cb) {
+  cb = cb || noop
+  fs._curOpen ++
+  fs._originalFs.writeFile.call(fs, path, data, options, function (er) {
+    onclose()
+    cb(er)
+  })
+}
+
+function WriteFileReq (path, data, options, cb) {
+  this.path = path
+  this.data = data
+  this.options = options
+  this.cb = cb
+}
+
+
+// (re-)implement some things that are known busted or missing.
+
+var constants = require("constants")
+
+// lchmod, broken prior to 0.6.2
+// back-port the fix here.
+if (constants.hasOwnProperty('O_SYMLINK') &&
+    process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
+  fs.lchmod = function (path, mode, callback) {
+    callback = callback || noop
+    fs.open( path
+           , constants.O_WRONLY | constants.O_SYMLINK
+           , mode
+           , function (err, fd) {
+      if (err) {
+        callback(err)
+        return
+      }
+      // prefer to return the chmod error, if one occurs,
+      // but still try to close, and report closing errors if they occur.
+      fs.fchmod(fd, mode, function (err) {
+        fs.close(fd, function(err2) {
+          callback(err || err2)
+        })
+      })
+    })
+  }
+
+  fs.lchmodSync = function (path, mode) {
+    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
+
+    // prefer to return the chmod error, if one occurs,
+    // but still try to close, and report closing errors if they occur.
+    var err, err2
+    try {
+      var ret = fs.fchmodSync(fd, mode)
+    } catch (er) {
+      err = er
+    }
+    try {
+      fs.closeSync(fd)
+    } catch (er) {
+      err2 = er
+    }
+    if (err || err2) throw (err || err2)
+    return ret
+  }
+}
+
+
+// lutimes implementation, or no-op
+if (!fs.lutimes) {
+  if (constants.hasOwnProperty("O_SYMLINK")) {
+    fs.lutimes = function (path, at, mt, cb) {
+      fs.open(path, constants.O_SYMLINK, function (er, fd) {
+        cb = cb || noop
+        if (er) return cb(er)
+        fs.futimes(fd, at, mt, function (er) {
+          fs.close(fd, function (er2) {
+            return cb(er || er2)
+          })
+        })
+      })
+    }
+
+    fs.lutimesSync = function (path, at, mt) {
+      var fd = fs.openSync(path, constants.O_SYMLINK)
+        , err
+        , err2
+        , ret
+
+      try {
+        var ret = fs.futimesSync(fd, at, mt)
+      } catch (er) {
+        err = er
+      }
+      try {
+        fs.closeSync(fd)
+      } catch (er) {
+        err2 = er
+      }
+      if (err || err2) throw (err || err2)
+      return ret
+    }
+
+  } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
+    // maybe utimensat will be bound soonish?
+    fs.lutimes = function (path, at, mt, cb) {
+      fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
+    }
+
+    fs.lutimesSync = function (path, at, mt) {
+      return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
+    }
+
+  } else {
+    fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
+    fs.lutimesSync = function () {}
+  }
+}
+
+
+// https://github.com/isaacs/node-graceful-fs/issues/4
+// Chown should not fail on einval or eperm if non-root.
+
+fs.chown = chownFix(fs.chown)
+fs.fchown = chownFix(fs.fchown)
+fs.lchown = chownFix(fs.lchown)
+
+fs.chownSync = chownFixSync(fs.chownSync)
+fs.fchownSync = chownFixSync(fs.fchownSync)
+fs.lchownSync = chownFixSync(fs.lchownSync)
+
+function chownFix (orig) {
+  if (!orig) return orig
+  return function (target, uid, gid, cb) {
+    return orig.call(fs, target, uid, gid, function (er, res) {
+      if (chownErOk(er)) er = null
+      cb(er, res)
+    })
+  }
+}
+
+function chownFixSync (orig) {
+  if (!orig) return orig
+  return function (target, uid, gid) {
+    try {
+      return orig.call(fs, target, uid, gid)
+    } catch (er) {
+      if (!chownErOk(er)) throw er
+    }
+  }
+}
+
+function chownErOk (er) {
+  // if there's no getuid, or if getuid() is something other than 0,
+  // and the error is EINVAL or EPERM, then just ignore it.
+  // This specific case is a silent failure in cp, install, tar,
+  // and most other unix tools that manage permissions.
+  // When running as root, or if other types of errors are encountered,
+  // then it's strict.
+  if (!er || (!process.getuid || process.getuid() !== 0)
+      && (er.code === "EINVAL" || er.code === "EPERM")) return true
+}
+
+
+// if lchmod/lchown do not exist, then make them no-ops
+if (!fs.lchmod) {
+  fs.lchmod = function (path, mode, cb) {
+    process.nextTick(cb)
+  }
+  fs.lchmodSync = function () {}
+}
+if (!fs.lchown) {
+  fs.lchown = function (path, uid, gid, cb) {
+    process.nextTick(cb)
+  }
+  fs.lchownSync = function () {}
+}
+
+
+
+// on Windows, A/V software can lock the directory, causing this
+// to fail with an EACCES or EPERM if the directory contains newly
+// created files.  Try again on failure, for up to 1 second.
+if (process.platform === "win32") {
+  var rename_ = fs.rename
+  fs.rename = function rename (from, to, cb) {
+    var start = Date.now()
+    rename_(from, to, function CB (er) {
+      if (er
+          && (er.code === "EACCES" || er.code === "EPERM")
+          && Date.now() - start < 1000) {
+        return rename_(from, to, CB)
+      }
+      cb(er)
+    })
+  }
+}
+
+
+// if read() returns EAGAIN, then just try it again.
+var read = fs.read
+fs.read = function (fd, buffer, offset, length, position, callback_) {
+  var callback
+  if (callback_ && typeof callback_ === 'function') {
+    var eagCounter = 0
+    callback = function (er, _, __) {
+      if (er && er.code === 'EAGAIN' && eagCounter < 10) {
+        eagCounter ++
+        return read.call(fs, fd, buffer, offset, length, position, callback)
+      }
+      callback_.apply(this, arguments)
+    }
+  }
+  return read.call(fs, fd, buffer, offset, length, position, callback)
+}
+
+var readSync = fs.readSync
+fs.readSync = function (fd, buffer, offset, length, position) {
+  var eagCounter = 0
+  while (true) {
+    try {
+      return readSync.call(fs, fd, buffer, offset, length, position)
+    } catch (er) {
+      if (er.code === 'EAGAIN' && eagCounter < 10) {
+        eagCounter ++
+        continue
+      }
+      throw er
+    }
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/package.json	(revision 533)
@@ -0,0 +1,49 @@
+{
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me"
+  },
+  "name": "graceful-fs",
+  "description": "A drop-in replacement for fs, making various improvements.",
+  "version": "1.2.3",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/node-graceful-fs.git"
+  },
+  "main": "graceful-fs.js",
+  "engines": {
+    "node": ">=0.4.0"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "keywords": [
+    "fs",
+    "module",
+    "reading",
+    "retry",
+    "retries",
+    "queue",
+    "error",
+    "errors",
+    "handling",
+    "EMFILE",
+    "EAGAIN",
+    "EINVAL",
+    "EPERM",
+    "EACCESS"
+  ],
+  "license": "BSD",
+  "readme": "# graceful-fs\n\ngraceful-fs functions as a drop-in replacement for the fs module,\nmaking various improvements.\n\nThe improvements are meant to normalize behavior across different\nplatforms and environments, and to make filesystem access more\nresilient to errors.\n\n## Improvements over fs module\n\ngraceful-fs:\n\n* keeps track of how many file descriptors are open, and by default\n  limits this to 1024. Any further requests to open a file are put in a\n  queue until new slots become available. If 1024 turns out to be too\n  much, it decreases the limit further.\n* fixes `lchmod` for Node versions prior to 0.6.2.\n* implements `fs.lutimes` if possible. Otherwise it becomes a noop.\n* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or\n  `lchown` if the user isn't root.\n* makes `lchmod` and `lchown` become noops, if not available.\n* retries reading a file if `read` results in EAGAIN error.\n\nOn Windows, it retries renaming a file for up to one second if `EACCESS`\nor `EPERM` error occurs, likely because antivirus software has locked\nthe directory.\n\n## Configuration\n\nThe maximum number of open file descriptors that graceful-fs manages may\nbe adjusted by setting `fs.MAX_OPEN` to a different number. The default\nis 1024.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/node-graceful-fs/issues"
+  },
+  "homepage": "https://github.com/isaacs/node-graceful-fs",
+  "_id": "graceful-fs@1.2.3",
+  "_from": "graceful-fs@~1.2.0"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/test/open.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/test/open.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/test/open.js	(revision 533)
@@ -0,0 +1,46 @@
+var test = require('tap').test
+var fs = require('../graceful-fs.js')
+
+test('graceful fs is not fs', function (t) {
+  t.notEqual(fs, require('fs'))
+  t.end()
+})
+
+test('open an existing file works', function (t) {
+  var start = fs._curOpen
+  var fd = fs.openSync(__filename, 'r')
+  t.equal(fs._curOpen, start + 1)
+  fs.closeSync(fd)
+  t.equal(fs._curOpen, start)
+  fs.open(__filename, 'r', function (er, fd) {
+    if (er) throw er
+    t.equal(fs._curOpen, start + 1)
+    fs.close(fd, function (er) {
+      if (er) throw er
+      t.equal(fs._curOpen, start)
+      t.end()
+    })
+  })
+})
+
+test('open a non-existing file throws', function (t) {
+  var start = fs._curOpen
+  var er
+  try {
+    var fd = fs.openSync('this file does not exist', 'r')
+  } catch (x) {
+    er = x
+  }
+  t.ok(er, 'should throw')
+  t.notOk(fd, 'should not get an fd')
+  t.equal(er.code, 'ENOENT')
+  t.equal(fs._curOpen, start)
+
+  fs.open('neither does this file', 'r', function (er, fd) {
+    t.ok(er, 'should throw')
+    t.notOk(fd, 'should not get an fd')
+    t.equal(er.code, 'ENOENT')
+    t.equal(fs._curOpen, start)
+    t.end()
+  })
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/test/ulimit.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/test/ulimit.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs/test/ulimit.js	(revision 533)
@@ -0,0 +1,158 @@
+var test = require('tap').test
+
+// simulated ulimit
+// this is like graceful-fs, but in reverse
+var fs_ = require('fs')
+var fs = require('../graceful-fs.js')
+var files = fs.readdirSync(__dirname)
+
+// Ok, no more actual file reading!
+
+var fds = 0
+var nextFd = 60
+var limit = 8
+fs_.open = function (path, flags, mode, cb) {
+  process.nextTick(function() {
+    ++fds
+    if (fds >= limit) {
+      --fds
+      var er = new Error('EMFILE Curses!')
+      er.code = 'EMFILE'
+      er.path = path
+      return cb(er)
+    } else {
+      cb(null, nextFd++)
+    }
+  })
+}
+
+fs_.openSync = function (path, flags, mode) {
+  if (fds >= limit) {
+    var er = new Error('EMFILE Curses!')
+    er.code = 'EMFILE'
+    er.path = path
+    throw er
+  } else {
+    ++fds
+    return nextFd++
+  }
+}
+
+fs_.close = function (fd, cb) {
+  process.nextTick(function () {
+    --fds
+    cb()
+  })
+}
+
+fs_.closeSync = function (fd) {
+  --fds
+}
+
+fs_.readdir = function (path, cb) {
+  process.nextTick(function() {
+    if (fds >= limit) {
+      var er = new Error('EMFILE Curses!')
+      er.code = 'EMFILE'
+      er.path = path
+      return cb(er)
+    } else {
+      ++fds
+      process.nextTick(function () {
+        --fds
+        cb(null, [__filename, "some-other-file.js"])
+      })
+    }
+  })
+}
+
+fs_.readdirSync = function (path) {
+  if (fds >= limit) {
+    var er = new Error('EMFILE Curses!')
+    er.code = 'EMFILE'
+    er.path = path
+    throw er
+  } else {
+    return [__filename, "some-other-file.js"]
+  }
+}
+
+
+test('open emfile autoreduce', function (t) {
+  fs.MIN_MAX_OPEN = 4
+  t.equal(fs.MAX_OPEN, 1024)
+
+  var max = 12
+  for (var i = 0; i < max; i++) {
+    fs.open(__filename, 'r', next(i))
+  }
+
+  var phase = 0
+
+  var expect =
+      [ [ 0, 60, null, 1024, 4, 12, 1 ],
+        [ 1, 61, null, 1024, 4, 12, 2 ],
+        [ 2, 62, null, 1024, 4, 12, 3 ],
+        [ 3, 63, null, 1024, 4, 12, 4 ],
+        [ 4, 64, null, 1024, 4, 12, 5 ],
+        [ 5, 65, null, 1024, 4, 12, 6 ],
+        [ 6, 66, null, 1024, 4, 12, 7 ],
+        [ 7, 67, null, 6, 4, 5, 1 ],
+        [ 8, 68, null, 6, 4, 5, 2 ],
+        [ 9, 69, null, 6, 4, 5, 3 ],
+        [ 10, 70, null, 6, 4, 5, 4 ],
+        [ 11, 71, null, 6, 4, 5, 5 ] ]
+
+  var actual = []
+
+  function next (i) { return function (er, fd) {
+    if (er)
+      throw er
+    actual.push([i, fd, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds])
+
+    if (i === max - 1) {
+      t.same(actual, expect)
+      t.ok(fs.MAX_OPEN < limit)
+      t.end()
+    }
+
+    fs.close(fd)
+  } }
+})
+
+test('readdir emfile autoreduce', function (t) {
+  fs.MAX_OPEN = 1024
+  var max = 12
+  for (var i = 0; i < max; i ++) {
+    fs.readdir(__dirname, next(i))
+  }
+
+  var expect =
+      [ [0,[__filename,"some-other-file.js"],null,7,4,7,7],
+        [1,[__filename,"some-other-file.js"],null,7,4,7,6],
+        [2,[__filename,"some-other-file.js"],null,7,4,7,5],
+        [3,[__filename,"some-other-file.js"],null,7,4,7,4],
+        [4,[__filename,"some-other-file.js"],null,7,4,7,3],
+        [5,[__filename,"some-other-file.js"],null,7,4,6,2],
+        [6,[__filename,"some-other-file.js"],null,7,4,5,1],
+        [7,[__filename,"some-other-file.js"],null,7,4,4,0],
+        [8,[__filename,"some-other-file.js"],null,7,4,3,3],
+        [9,[__filename,"some-other-file.js"],null,7,4,2,2],
+        [10,[__filename,"some-other-file.js"],null,7,4,1,1],
+        [11,[__filename,"some-other-file.js"],null,7,4,0,0] ]
+
+  var actual = []
+
+  function next (i) { return function (er, files) {
+    if (er)
+      throw er
+    var line = [i, files, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds ]
+    actual.push(line)
+
+    if (i === max - 1) {
+      t.ok(fs.MAX_OPEN < limit)
+      t.same(actual, expect)
+      t.end()
+    }
+  } }
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/README.md	(revision 533)
@@ -0,0 +1,51 @@
+A dead simple way to do inheritance in JS.
+
+    var inherits = require("inherits")
+
+    function Animal () {
+      this.alive = true
+    }
+    Animal.prototype.say = function (what) {
+      console.log(what)
+    }
+
+    inherits(Dog, Animal)
+    function Dog () {
+      Dog.super.apply(this)
+    }
+    Dog.prototype.sniff = function () {
+      this.say("sniff sniff")
+    }
+    Dog.prototype.bark = function () {
+      this.say("woof woof")
+    }
+
+    inherits(Chihuahua, Dog)
+    function Chihuahua () {
+      Chihuahua.super.apply(this)
+    }
+    Chihuahua.prototype.bark = function () {
+      this.say("yip yip")
+    }
+
+    // also works
+    function Cat () {
+      Cat.super.apply(this)
+    }
+    Cat.prototype.hiss = function () {
+      this.say("CHSKKSS!!")
+    }
+    inherits(Cat, Animal, {
+      meow: function () { this.say("miao miao") }
+    })
+    Cat.prototype.purr = function () {
+      this.say("purr purr")
+    }
+
+
+    var c = new Chihuahua
+    assert(c instanceof Chihuahua)
+    assert(c instanceof Dog)
+    assert(c instanceof Animal)
+
+The actual function is laughably small.  10-lines small.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/inherits.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/inherits.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/inherits.js	(revision 533)
@@ -0,0 +1,29 @@
+module.exports = inherits
+
+function inherits (c, p, proto) {
+  proto = proto || {}
+  var e = {}
+  ;[c.prototype, proto].forEach(function (s) {
+    Object.getOwnPropertyNames(s).forEach(function (k) {
+      e[k] = Object.getOwnPropertyDescriptor(s, k)
+    })
+  })
+  c.prototype = Object.create(p.prototype, e)
+  c.super = p
+}
+
+//function Child () {
+//  Child.super.call(this)
+//  console.error([this
+//                ,this.constructor
+//                ,this.constructor === Child
+//                ,this.constructor.super === Parent
+//                ,Object.getPrototypeOf(this) === Child.prototype
+//                ,Object.getPrototypeOf(Object.getPrototypeOf(this))
+//                 === Parent.prototype
+//                ,this instanceof Child
+//                ,this instanceof Parent])
+//}
+//function Parent () {}
+//inherits(Child, Parent)
+//new Child
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/inherits/package.json	(revision 533)
@@ -0,0 +1,30 @@
+{
+  "name": "inherits",
+  "description": "A tiny simple way to do classic inheritance in js",
+  "version": "1.0.0",
+  "keywords": [
+    "inheritance",
+    "class",
+    "klass",
+    "oop",
+    "object-oriented"
+  ],
+  "main": "./inherits.js",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/isaacs/inherits"
+  },
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me/"
+  },
+  "readme": "A dead simple way to do inheritance in JS.\n\n    var inherits = require(\"inherits\")\n\n    function Animal () {\n      this.alive = true\n    }\n    Animal.prototype.say = function (what) {\n      console.log(what)\n    }\n\n    inherits(Dog, Animal)\n    function Dog () {\n      Dog.super.apply(this)\n    }\n    Dog.prototype.sniff = function () {\n      this.say(\"sniff sniff\")\n    }\n    Dog.prototype.bark = function () {\n      this.say(\"woof woof\")\n    }\n\n    inherits(Chihuahua, Dog)\n    function Chihuahua () {\n      Chihuahua.super.apply(this)\n    }\n    Chihuahua.prototype.bark = function () {\n      this.say(\"yip yip\")\n    }\n\n    // also works\n    function Cat () {\n      Cat.super.apply(this)\n    }\n    Cat.prototype.hiss = function () {\n      this.say(\"CHSKKSS!!\")\n    }\n    inherits(Cat, Animal, {\n      meow: function () { this.say(\"miao miao\") }\n    })\n    Cat.prototype.purr = function () {\n      this.say(\"purr purr\")\n    }\n\n\n    var c = new Chihuahua\n    assert(c instanceof Chihuahua)\n    assert(c instanceof Dog)\n    assert(c instanceof Animal)\n\nThe actual function is laughably small.  10-lines small.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/inherits/issues"
+  },
+  "homepage": "https://github.com/isaacs/inherits",
+  "_id": "inherits@1.0.0",
+  "_from": "inherits@1"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/package.json	(revision 533)
@@ -0,0 +1,40 @@
+{
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me/"
+  },
+  "name": "glob",
+  "description": "a little globber",
+  "version": "3.1.21",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/node-glob.git"
+  },
+  "main": "glob.js",
+  "engines": {
+    "node": "*"
+  },
+  "dependencies": {
+    "minimatch": "~0.2.11",
+    "graceful-fs": "~1.2.0",
+    "inherits": "1"
+  },
+  "devDependencies": {
+    "tap": "~0.4.0",
+    "mkdirp": "0",
+    "rimraf": "1"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "license": "BSD",
+  "readme": "# Glob\n\nThis is a glob implementation in JavaScript.  It uses the `minimatch`\nlibrary to do its matching.\n\n## Attention: node-glob users!\n\nThe API has changed dramatically between 2.x and 3.x. This library is\nnow 100% JavaScript, and the integer flags have been replaced with an\noptions object.\n\nAlso, there's an event emitter class, proper tests, and all the other\nthings you've come to expect from node modules.\n\nAnd best of all, no compilation!\n\n## Usage\n\n```javascript\nvar glob = require(\"glob\")\n\n// options is optional\nglob(\"**/*.js\", options, function (er, files) {\n  // files is an array of filenames.\n  // If the `nonull` option is set, and nothing\n  // was found, then files is [\"**/*.js\"]\n  // er is an error object or null.\n})\n```\n\n## Features\n\nPlease see the [minimatch\ndocumentation](https://github.com/isaacs/minimatch) for more details.\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n* [minimatch documentation](https://github.com/isaacs/minimatch)\n\n## glob(pattern, [options], cb)\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* `cb` {Function}\n  * `err` {Error | null}\n  * `matches` {Array<String>} filenames found matching the pattern\n\nPerform an asynchronous glob search.\n\n## glob.sync(pattern, [options]\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* return: {Array<String>} filenames found matching the pattern\n\nPerform a synchronous glob search.\n\n## Class: glob.Glob\n\nCreate a Glob object by instanting the `glob.Glob` class.\n\n```javascript\nvar Glob = require(\"glob\").Glob\nvar mg = new Glob(pattern, options, cb)\n```\n\nIt's an EventEmitter, and starts walking the filesystem to find matches\nimmediately.\n\n### new glob.Glob(pattern, [options], [cb])\n\n* `pattern` {String} pattern to search for\n* `options` {Object}\n* `cb` {Function} Called when an error occurs, or matches are found\n  * `err` {Error | null}\n  * `matches` {Array<String>} filenames found matching the pattern\n\nNote that if the `sync` flag is set in the options, then matches will\nbe immediately available on the `g.found` member.\n\n### Properties\n\n* `minimatch` The minimatch object that the glob uses.\n* `options` The options object passed in.\n* `error` The error encountered.  When an error is encountered, the\n  glob object is in an undefined state, and should be discarded.\n* `aborted` Boolean which is set to true when calling `abort()`.  There\n  is no way at this time to continue a glob search after aborting, but\n  you can re-use the statCache to avoid having to duplicate syscalls.\n\n### Events\n\n* `end` When the matching is finished, this is emitted with all the\n  matches found.  If the `nonull` option is set, and no match was found,\n  then the `matches` list contains the original pattern.  The matches\n  are sorted, unless the `nosort` flag is set.\n* `match` Every time a match is found, this is emitted with the matched.\n* `error` Emitted when an unexpected error is encountered, or whenever\n  any fs error occurs if `options.strict` is set.\n* `abort` When `abort()` is called, this event is raised.\n\n### Methods\n\n* `abort` Stop the search.\n\n### Options\n\nAll the options that can be passed to Minimatch can also be passed to\nGlob to change pattern matching behavior.  Also, some have been added,\nor have glob-specific ramifications.\n\nAll options are false by default, unless otherwise noted.\n\nAll options are added to the glob object, as well.\n\n* `cwd` The current working directory in which to search.  Defaults\n  to `process.cwd()`.\n* `root` The place where patterns starting with `/` will be mounted\n  onto.  Defaults to `path.resolve(options.cwd, \"/\")` (`/` on Unix\n  systems, and `C:\\` or some such on Windows.)\n* `nomount` By default, a pattern starting with a forward-slash will be\n  \"mounted\" onto the root setting, so that a valid filesystem path is\n  returned.  Set this flag to disable that behavior.\n* `mark` Add a `/` character to directory matches.  Note that this\n  requires additional stat calls.\n* `nosort` Don't sort the results.\n* `stat` Set to true to stat *all* results.  This reduces performance\n  somewhat, and is completely unnecessary, unless `readdir` is presumed\n  to be an untrustworthy indicator of file existence.  It will cause\n  ELOOP to be triggered one level sooner in the case of cyclical\n  symbolic links.\n* `silent` When an unusual error is encountered\n  when attempting to read a directory, a warning will be printed to\n  stderr.  Set the `silent` option to true to suppress these warnings.\n* `strict` When an unusual error is encountered\n  when attempting to read a directory, the process will just continue on\n  in search of other matches.  Set the `strict` option to raise an error\n  in these cases.\n* `statCache` A cache of results of filesystem information, to prevent\n  unnecessary stat calls.  While it should not normally be necessary to\n  set this, you may pass the statCache from one glob() call to the\n  options object of another, if you know that the filesystem will not\n  change between calls.  (See \"Race Conditions\" below.)\n* `sync` Perform a synchronous glob search.\n* `nounique` In some cases, brace-expanded patterns can result in the\n  same file showing up multiple times in the result set.  By default,\n  this implementation prevents duplicates in the result set.\n  Set this flag to disable that behavior.\n* `nonull` Set to never return an empty set, instead returning a set\n  containing the pattern itself.  This is the default in glob(3).\n* `nocase` Perform a case-insensitive match.  Note that case-insensitive\n  filesystems will sometimes result in glob returning results that are\n  case-insensitively matched anyway, since readdir and stat will not\n  raise an error.\n* `debug` Set to enable debug logging in minimatch and glob.\n* `globDebug` Set to enable debug logging in glob, but not minimatch.\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between node-glob and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated.  Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally.  This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything.  Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set.  This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not.  **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen glob returns the pattern as-provided, rather than\ninterpreting the character escapes.  For example,\n`glob.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`.  This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern.  Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity.  Since those two are valid, matching proceeds.\n\n## Windows\n\n**Please only use forward-slashes in glob expressions.**\n\nThough windows uses either `/` or `\\` as its path separator, only `/`\ncharacters are used by this glob implementation.  You must use\nforward-slashes **only** in glob expressions.  Back-slashes will always\nbe interpreted as escape characters, not path separators.\n\nResults from absolute patterns such as `/foo/*` are mounted onto the\nroot setting using `path.join`.  On windows, this will by default result\nin `/foo/*` matching `C:\\foo\\bar.txt`.\n\n## Race Conditions\n\nGlob searching, by its very nature, is susceptible to race conditions,\nsince it relies on directory walking and such.\n\nAs a result, it is possible that a file that exists when glob looks for\nit may have been deleted or modified by the time it returns the result.\n\nAs part of its internal implementation, this program caches all stat\nand readdir calls that it makes, in order to cut down on system\noverhead.  However, this also makes it even more susceptible to races,\nespecially if the statCache object is reused between glob calls.\n\nUsers are thus advised not to use a glob result as a\nguarantee of filesystem state in the face of rapid changes.\nFor the vast majority of operations, this is never a problem.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/node-glob/issues"
+  },
+  "homepage": "https://github.com/isaacs/node-glob",
+  "_id": "glob@3.1.21",
+  "_from": "glob@~3.1.21"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/00-setup.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/00-setup.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/00-setup.js	(revision 533)
@@ -0,0 +1,176 @@
+// just a little pre-run script to set up the fixtures.
+// zz-finish cleans it up
+
+var mkdirp = require("mkdirp")
+var path = require("path")
+var i = 0
+var tap = require("tap")
+var fs = require("fs")
+var rimraf = require("rimraf")
+
+var files =
+[ "a/.abcdef/x/y/z/a"
+, "a/abcdef/g/h"
+, "a/abcfed/g/h"
+, "a/b/c/d"
+, "a/bc/e/f"
+, "a/c/d/c/b"
+, "a/cb/e/f"
+]
+
+var symlinkTo = path.resolve(__dirname, "a/symlink/a/b/c")
+var symlinkFrom = "../.."
+
+files = files.map(function (f) {
+  return path.resolve(__dirname, f)
+})
+
+tap.test("remove fixtures", function (t) {
+  rimraf(path.resolve(__dirname, "a"), function (er) {
+    t.ifError(er, "remove fixtures")
+    t.end()
+  })
+})
+
+files.forEach(function (f) {
+  tap.test(f, function (t) {
+    var d = path.dirname(f)
+    mkdirp(d, 0755, function (er) {
+      if (er) {
+        t.fail(er)
+        return t.bailout()
+      }
+      fs.writeFile(f, "i like tests", function (er) {
+        t.ifError(er, "make file")
+        t.end()
+      })
+    })
+  })
+})
+
+if (process.platform !== "win32") {
+  tap.test("symlinky", function (t) {
+    var d = path.dirname(symlinkTo)
+    console.error("mkdirp", d)
+    mkdirp(d, 0755, function (er) {
+      t.ifError(er)
+      fs.symlink(symlinkFrom, symlinkTo, "dir", function (er) {
+        t.ifError(er, "make symlink")
+        t.end()
+      })
+    })
+  })
+}
+
+;["foo","bar","baz","asdf","quux","qwer","rewq"].forEach(function (w) {
+  w = "/tmp/glob-test/" + w
+  tap.test("create " + w, function (t) {
+    mkdirp(w, function (er) {
+      if (er)
+        throw er
+      t.pass(w)
+      t.end()
+    })
+  })
+})
+
+
+// generate the bash pattern test-fixtures if possible
+if (process.platform === "win32" || !process.env.TEST_REGEN) {
+  console.error("Windows, or TEST_REGEN unset.  Using cached fixtures.")
+  return
+}
+
+var spawn = require("child_process").spawn;
+var globs =
+  // put more patterns here.
+  // anything that would be directly in / should be in /tmp/glob-test
+  ["test/a/*/+(c|g)/./d"
+  ,"test/a/**/[cg]/../[cg]"
+  ,"test/a/{b,c,d,e,f}/**/g"
+  ,"test/a/b/**"
+  ,"test/**/g"
+  ,"test/a/abc{fed,def}/g/h"
+  ,"test/a/abc{fed/g,def}/**/"
+  ,"test/a/abc{fed/g,def}/**///**/"
+  ,"test/**/a/**/"
+  ,"test/+(a|b|c)/a{/,bc*}/**"
+  ,"test/*/*/*/f"
+  ,"test/**/f"
+  ,"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**"
+  ,"{./*/*,/tmp/glob-test/*}"
+  ,"{/tmp/glob-test/*,*}" // evil owl face!  how you taunt me!
+  ,"test/a/!(symlink)/**"
+  ]
+var bashOutput = {}
+var fs = require("fs")
+
+globs.forEach(function (pattern) {
+  tap.test("generate fixture " + pattern, function (t) {
+    var cmd = "shopt -s globstar && " +
+              "shopt -s extglob && " +
+              "shopt -s nullglob && " +
+              // "shopt >&2; " +
+              "eval \'for i in " + pattern + "; do echo $i; done\'"
+    var cp = spawn("bash", ["-c", cmd], { cwd: path.dirname(__dirname) })
+    var out = []
+    cp.stdout.on("data", function (c) {
+      out.push(c)
+    })
+    cp.stderr.pipe(process.stderr)
+    cp.on("close", function (code) {
+      out = flatten(out)
+      if (!out)
+        out = []
+      else
+        out = cleanResults(out.split(/\r*\n/))
+
+      bashOutput[pattern] = out
+      t.notOk(code, "bash test should finish nicely")
+      t.end()
+    })
+  })
+})
+
+tap.test("save fixtures", function (t) {
+  var fname = path.resolve(__dirname, "bash-results.json")
+  var data = JSON.stringify(bashOutput, null, 2) + "\n"
+  fs.writeFile(fname, data, function (er) {
+    t.ifError(er)
+    t.end()
+  })
+})
+
+function cleanResults (m) {
+  // normalize discrepancies in ordering, duplication,
+  // and ending slashes.
+  return m.map(function (m) {
+    return m.replace(/\/+/g, "/").replace(/\/$/, "")
+  }).sort(alphasort).reduce(function (set, f) {
+    if (f !== set[set.length - 1]) set.push(f)
+    return set
+  }, []).sort(alphasort).map(function (f) {
+    // de-windows
+    return (process.platform !== 'win32') ? f
+           : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/')
+  })
+}
+
+function flatten (chunks) {
+  var s = 0
+  chunks.forEach(function (c) { s += c.length })
+  var out = new Buffer(s)
+  s = 0
+  chunks.forEach(function (c) {
+    c.copy(out, s)
+    s += c.length
+  })
+
+  return out.toString().trim()
+}
+
+function alphasort (a, b) {
+  a = a.toLowerCase()
+  b = b.toLowerCase()
+  return a > b ? 1 : a < b ? -1 : 0
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/bash-comparison.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/bash-comparison.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/bash-comparison.js	(revision 533)
@@ -0,0 +1,63 @@
+// basic test
+// show that it does the same thing by default as the shell.
+var tap = require("tap")
+, child_process = require("child_process")
+, bashResults = require("./bash-results.json")
+, globs = Object.keys(bashResults)
+, glob = require("../")
+, path = require("path")
+
+// run from the root of the project
+// this is usually where you're at anyway, but be sure.
+process.chdir(path.resolve(__dirname, ".."))
+
+function alphasort (a, b) {
+  a = a.toLowerCase()
+  b = b.toLowerCase()
+  return a > b ? 1 : a < b ? -1 : 0
+}
+
+globs.forEach(function (pattern) {
+  var expect = bashResults[pattern]
+  // anything regarding the symlink thing will fail on windows, so just skip it
+  if (process.platform === "win32" &&
+      expect.some(function (m) {
+        return /\/symlink\//.test(m)
+      }))
+    return
+
+  tap.test(pattern, function (t) {
+    glob(pattern, function (er, matches) {
+      if (er)
+        throw er
+
+      // sort and unmark, just to match the shell results
+      matches = cleanResults(matches)
+
+      t.deepEqual(matches, expect, pattern)
+      t.end()
+    })
+  })
+
+  tap.test(pattern + " sync", function (t) {
+    var matches = cleanResults(glob.sync(pattern))
+
+    t.deepEqual(matches, expect, "should match shell")
+    t.end()
+  })
+})
+
+function cleanResults (m) {
+  // normalize discrepancies in ordering, duplication,
+  // and ending slashes.
+  return m.map(function (m) {
+    return m.replace(/\/+/g, "/").replace(/\/$/, "")
+  }).sort(alphasort).reduce(function (set, f) {
+    if (f !== set[set.length - 1]) set.push(f)
+    return set
+  }, []).sort(alphasort).map(function (f) {
+    // de-windows
+    return (process.platform !== 'win32') ? f
+           : f.replace(/^[a-zA-Z]:[\/\\]+/, '/').replace(/[\\\/]+/g, '/')
+  })
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/bash-results.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/bash-results.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/bash-results.json	(revision 533)
@@ -0,0 +1,348 @@
+{
+  "test/a/*/+(c|g)/./d": [
+    "test/a/b/c/./d"
+  ],
+  "test/a/**/[cg]/../[cg]": [
+    "test/a/abcdef/g/../g",
+    "test/a/abcfed/g/../g",
+    "test/a/b/c/../c",
+    "test/a/c/../c",
+    "test/a/c/d/c/../c",
+    "test/a/symlink/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c"
+  ],
+  "test/a/{b,c,d,e,f}/**/g": [],
+  "test/a/b/**": [
+    "test/a/b",
+    "test/a/b/c",
+    "test/a/b/c/d"
+  ],
+  "test/**/g": [
+    "test/a/abcdef/g",
+    "test/a/abcfed/g"
+  ],
+  "test/a/abc{fed,def}/g/h": [
+    "test/a/abcdef/g/h",
+    "test/a/abcfed/g/h"
+  ],
+  "test/a/abc{fed/g,def}/**/": [
+    "test/a/abcdef",
+    "test/a/abcdef/g",
+    "test/a/abcfed/g"
+  ],
+  "test/a/abc{fed/g,def}/**///**/": [
+    "test/a/abcdef",
+    "test/a/abcdef/g",
+    "test/a/abcfed/g"
+  ],
+  "test/**/a/**/": [
+    "test/a",
+    "test/a/abcdef",
+    "test/a/abcdef/g",
+    "test/a/abcfed",
+    "test/a/abcfed/g",
+    "test/a/b",
+    "test/a/b/c",
+    "test/a/bc",
+    "test/a/bc/e",
+    "test/a/c",
+    "test/a/c/d",
+    "test/a/c/d/c",
+    "test/a/cb",
+    "test/a/cb/e",
+    "test/a/symlink",
+    "test/a/symlink/a",
+    "test/a/symlink/a/b",
+    "test/a/symlink/a/b/c",
+    "test/a/symlink/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b"
+  ],
+  "test/+(a|b|c)/a{/,bc*}/**": [
+    "test/a/abcdef",
+    "test/a/abcdef/g",
+    "test/a/abcdef/g/h",
+    "test/a/abcfed",
+    "test/a/abcfed/g",
+    "test/a/abcfed/g/h"
+  ],
+  "test/*/*/*/f": [
+    "test/a/bc/e/f",
+    "test/a/cb/e/f"
+  ],
+  "test/**/f": [
+    "test/a/bc/e/f",
+    "test/a/cb/e/f"
+  ],
+  "test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**": [
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+    "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c"
+  ],
+  "{./*/*,/tmp/glob-test/*}": [
+    "./examples/g.js",
+    "./examples/usr-local.js",
+    "./node_modules/graceful-fs",
+    "./node_modules/inherits",
+    "./node_modules/minimatch",
+    "./node_modules/mkdirp",
+    "./node_modules/rimraf",
+    "./node_modules/tap",
+    "./test/00-setup.js",
+    "./test/a",
+    "./test/bash-comparison.js",
+    "./test/bash-results.json",
+    "./test/cwd-test.js",
+    "./test/mark.js",
+    "./test/nocase-nomagic.js",
+    "./test/pause-resume.js",
+    "./test/root-nomount.js",
+    "./test/root.js",
+    "./test/zz-cleanup.js",
+    "/tmp/glob-test/asdf",
+    "/tmp/glob-test/bar",
+    "/tmp/glob-test/baz",
+    "/tmp/glob-test/foo",
+    "/tmp/glob-test/quux",
+    "/tmp/glob-test/qwer",
+    "/tmp/glob-test/rewq"
+  ],
+  "{/tmp/glob-test/*,*}": [
+    "/tmp/glob-test/asdf",
+    "/tmp/glob-test/bar",
+    "/tmp/glob-test/baz",
+    "/tmp/glob-test/foo",
+    "/tmp/glob-test/quux",
+    "/tmp/glob-test/qwer",
+    "/tmp/glob-test/rewq",
+    "examples",
+    "glob.js",
+    "LICENSE",
+    "node_modules",
+    "package.json",
+    "README.md",
+    "test"
+  ],
+  "test/a/!(symlink)/**": [
+    "test/a/abcdef",
+    "test/a/abcdef/g",
+    "test/a/abcdef/g/h",
+    "test/a/abcfed",
+    "test/a/abcfed/g",
+    "test/a/abcfed/g/h",
+    "test/a/b",
+    "test/a/b/c",
+    "test/a/b/c/d",
+    "test/a/bc",
+    "test/a/bc/e",
+    "test/a/bc/e/f",
+    "test/a/c",
+    "test/a/c/d",
+    "test/a/c/d/c",
+    "test/a/c/d/c/b",
+    "test/a/cb",
+    "test/a/cb/e",
+    "test/a/cb/e/f"
+  ]
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/cwd-test.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/cwd-test.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/cwd-test.js	(revision 533)
@@ -0,0 +1,55 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing cwd and searching for **/d", function (t) {
+  var glob = require('../')
+  var path = require('path')
+  t.test('.', function (t) {
+    glob('**/d', function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('a', function (t) {
+    glob('**/d', {cwd:path.resolve('a')}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'b/c/d', 'c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('a/b', function (t) {
+    glob('**/d', {cwd:path.resolve('a/b')}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('a/b/', function (t) {
+    glob('**/d', {cwd:path.resolve('a/b/')}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('.', function (t) {
+    glob('**/d', {cwd: process.cwd()}, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
+      t.end()
+    })
+  })
+
+  t.test('cd -', function (t) {
+    process.chdir(origCwd)
+    t.end()
+  })
+
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/mark.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/mark.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/mark.js	(revision 533)
@@ -0,0 +1,74 @@
+var test = require("tap").test
+var glob = require('../')
+process.chdir(__dirname)
+
+test("mark, no / on pattern", function (t) {
+  glob("a/*", {mark: true}, function (er, results) {
+    if (er)
+      throw er
+    var expect = [ 'a/abcdef/',
+                   'a/abcfed/',
+                   'a/b/',
+                   'a/bc/',
+                   'a/c/',
+                   'a/cb/' ]
+
+    if (process.platform !== "win32")
+      expect.push('a/symlink/')
+
+    t.same(results, expect)
+    t.end()
+  })
+})
+
+test("mark=false, no / on pattern", function (t) {
+  glob("a/*", function (er, results) {
+    if (er)
+      throw er
+    var expect = [ 'a/abcdef',
+                   'a/abcfed',
+                   'a/b',
+                   'a/bc',
+                   'a/c',
+                   'a/cb' ]
+
+    if (process.platform !== "win32")
+      expect.push('a/symlink')
+    t.same(results, expect)
+    t.end()
+  })
+})
+
+test("mark=true, / on pattern", function (t) {
+  glob("a/*/", {mark: true}, function (er, results) {
+    if (er)
+      throw er
+    var expect = [ 'a/abcdef/',
+                    'a/abcfed/',
+                    'a/b/',
+                    'a/bc/',
+                    'a/c/',
+                    'a/cb/' ]
+    if (process.platform !== "win32")
+      expect.push('a/symlink/')
+    t.same(results, expect)
+    t.end()
+  })
+})
+
+test("mark=false, / on pattern", function (t) {
+  glob("a/*/", function (er, results) {
+    if (er)
+      throw er
+    var expect = [ 'a/abcdef/',
+                   'a/abcfed/',
+                   'a/b/',
+                   'a/bc/',
+                   'a/c/',
+                   'a/cb/' ]
+    if (process.platform !== "win32")
+      expect.push('a/symlink/')
+    t.same(results, expect)
+    t.end()
+  })
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/nocase-nomagic.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/nocase-nomagic.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/nocase-nomagic.js	(revision 533)
@@ -0,0 +1,113 @@
+var fs = require('graceful-fs');
+var test = require('tap').test;
+var glob = require('../');
+
+test('mock fs', function(t) {
+  var stat = fs.stat
+  var statSync = fs.statSync
+  var readdir = fs.readdir
+  var readdirSync = fs.readdirSync
+
+  function fakeStat(path) {
+    var ret
+    switch (path.toLowerCase()) {
+      case '/tmp': case '/tmp/':
+        ret = { isDirectory: function() { return true } }
+        break
+      case '/tmp/a':
+        ret = { isDirectory: function() { return false } }
+        break
+    }
+    return ret
+  }
+
+  fs.stat = function(path, cb) {
+    var f = fakeStat(path);
+    if (f) {
+      process.nextTick(function() {
+        cb(null, f)
+      })
+    } else {
+      stat.call(fs, path, cb)
+    }
+  }
+
+  fs.statSync = function(path) {
+    return fakeStat(path) || statSync.call(fs, path)
+  }
+
+  function fakeReaddir(path) {
+    var ret
+    switch (path.toLowerCase()) {
+      case '/tmp': case '/tmp/':
+        ret = [ 'a', 'A' ]
+        break
+      case '/':
+        ret = ['tmp', 'tMp', 'tMP', 'TMP']
+    }
+    return ret
+  }
+
+  fs.readdir = function(path, cb) {
+    var f = fakeReaddir(path)
+    if (f)
+      process.nextTick(function() {
+        cb(null, f)
+      })
+    else
+      readdir.call(fs, path, cb)
+  }
+
+  fs.readdirSync = function(path) {
+    return fakeReaddir(path) || readdirSync.call(fs, path)
+  }
+
+  t.pass('mocked')
+  t.end()
+})
+
+test('nocase, nomagic', function(t) {
+  var n = 2
+  var want = [ '/TMP/A',
+               '/TMP/a',
+               '/tMP/A',
+               '/tMP/a',
+               '/tMp/A',
+               '/tMp/a',
+               '/tmp/A',
+               '/tmp/a' ]
+  glob('/tmp/a', { nocase: true }, function(er, res) {
+    if (er)
+      throw er
+    t.same(res.sort(), want)
+    if (--n === 0) t.end()
+  })
+  glob('/tmp/A', { nocase: true }, function(er, res) {
+    if (er)
+      throw er
+    t.same(res.sort(), want)
+    if (--n === 0) t.end()
+  })
+})
+
+test('nocase, with some magic', function(t) {
+  t.plan(2)
+  var want = [ '/TMP/A',
+               '/TMP/a',
+               '/tMP/A',
+               '/tMP/a',
+               '/tMp/A',
+               '/tMp/a',
+               '/tmp/A',
+               '/tmp/a' ]
+  glob('/tmp/*', { nocase: true }, function(er, res) {
+    if (er)
+      throw er
+    t.same(res.sort(), want)
+  })
+  glob('/tmp/*', { nocase: true }, function(er, res) {
+    if (er)
+      throw er
+    t.same(res.sort(), want)
+  })
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/pause-resume.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/pause-resume.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/pause-resume.js	(revision 533)
@@ -0,0 +1,73 @@
+// show that no match events happen while paused.
+var tap = require("tap")
+, child_process = require("child_process")
+// just some gnarly pattern with lots of matches
+, pattern = "test/a/!(symlink)/**"
+, bashResults = require("./bash-results.json")
+, patterns = Object.keys(bashResults)
+, glob = require("../")
+, Glob = glob.Glob
+, path = require("path")
+
+// run from the root of the project
+// this is usually where you're at anyway, but be sure.
+process.chdir(path.resolve(__dirname, ".."))
+
+function alphasort (a, b) {
+  a = a.toLowerCase()
+  b = b.toLowerCase()
+  return a > b ? 1 : a < b ? -1 : 0
+}
+
+function cleanResults (m) {
+  // normalize discrepancies in ordering, duplication,
+  // and ending slashes.
+  return m.map(function (m) {
+    return m.replace(/\/+/g, "/").replace(/\/$/, "")
+  }).sort(alphasort).reduce(function (set, f) {
+    if (f !== set[set.length - 1]) set.push(f)
+    return set
+  }, []).sort(alphasort).map(function (f) {
+    // de-windows
+    return (process.platform !== 'win32') ? f
+           : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/')
+  })
+}
+
+var globResults = []
+tap.test("use a Glob object, and pause/resume it", function (t) {
+  var g = new Glob(pattern)
+  , paused = false
+  , res = []
+  , expect = bashResults[pattern]
+
+  g.on("pause", function () {
+    console.error("pause")
+  })
+
+  g.on("resume", function () {
+    console.error("resume")
+  })
+
+  g.on("match", function (m) {
+    t.notOk(g.paused, "must not be paused")
+    globResults.push(m)
+    g.pause()
+    t.ok(g.paused, "must be paused")
+    setTimeout(g.resume.bind(g), 10)
+  })
+
+  g.on("end", function (matches) {
+    t.pass("reached glob end")
+    globResults = cleanResults(globResults)
+    matches = cleanResults(matches)
+    t.deepEqual(matches, globResults,
+      "end event matches should be the same as match events")
+
+    t.deepEqual(matches, expect,
+      "glob matches should be the same as bash results")
+
+    t.end()
+  })
+})
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/root-nomount.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/root-nomount.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/root-nomount.js	(revision 533)
@@ -0,0 +1,39 @@
+var tap = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+tap.test("changing root and searching for /b*/**", function (t) {
+  var glob = require('../')
+  var path = require('path')
+  t.test('.', function (t) {
+    glob('/b*/**', { globDebug: true, root: '.', nomount: true }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [])
+      t.end()
+    })
+  })
+
+  t.test('a', function (t) {
+    glob('/b*/**', { globDebug: true, root: path.resolve('a'), nomount: true }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
+      t.end()
+    })
+  })
+
+  t.test('root=a, cwd=a/b', function (t) {
+    glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b'), nomount: true }, function (er, matches) {
+      t.ifError(er)
+      t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
+      t.end()
+    })
+  })
+
+  t.test('cd -', function (t) {
+    process.chdir(origCwd)
+    t.end()
+  })
+
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/root.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/root.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/root.js	(revision 533)
@@ -0,0 +1,46 @@
+var t = require("tap")
+
+var origCwd = process.cwd()
+process.chdir(__dirname)
+
+var glob = require('../')
+var path = require('path')
+
+t.test('.', function (t) {
+  glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) {
+    t.ifError(er)
+    t.like(matches, [])
+    t.end()
+  })
+})
+
+
+t.test('a', function (t) {
+  console.error("root=" + path.resolve('a'))
+  glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) {
+    t.ifError(er)
+    var wanted = [
+        '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f'
+      ].map(function (m) {
+        return path.join(path.resolve('a'), m).replace(/\\/g, '/')
+      })
+
+    t.like(matches, wanted)
+    t.end()
+  })
+})
+
+t.test('root=a, cwd=a/b', function (t) {
+  glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) {
+    t.ifError(er)
+    t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
+      return path.join(path.resolve('a'), m).replace(/\\/g, '/')
+    }))
+    t.end()
+  })
+})
+
+t.test('cd -', function (t) {
+  process.chdir(origCwd)
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/zz-cleanup.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/zz-cleanup.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/test/zz-cleanup.js	(revision 533)
@@ -0,0 +1,11 @@
+// remove the fixtures
+var tap = require("tap")
+, rimraf = require("rimraf")
+, path = require("path")
+
+tap.test("cleanup fixtures", function (t) {
+  rimraf(path.resolve(__dirname, "a"), function (er) {
+    t.ifError(er, "removed")
+    t.end()
+  })
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/LICENSE.txt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/LICENSE.txt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/LICENSE.txt	(revision 533)
@@ -0,0 +1,22 @@
+Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+Based on Underscore.js 1.4.3, copyright 2009-2013 Jeremy Ashkenas,
+DocumentCloud Inc. <http://underscorejs.org/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/README.md	(revision 533)
@@ -0,0 +1,276 @@
+# Lo-Dash <sup>v1.0.1</sup>
+[![build status](https://secure.travis-ci.org/bestiejs/lodash.png)](http://travis-ci.org/bestiejs/lodash)
+
+An alternative to Underscore.js, delivering consistency, [customization](https://github.com/bestiejs/lodash#custom-builds), [performance](http://lodash.com/benchmarks), and [extra features](https://github.com/bestiejs/lodash#features).
+
+## Download
+
+* Lo-Dash builds (for modern environments):<br>
+[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.js) and
+[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.min.js)
+
+* Lo-Dash compatibility builds (for legacy and modern environments):<br>
+[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.compat.js) and
+[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.compat.min.js)
+
+* Underscore compatibility builds:<br>
+[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.underscore.js) and
+[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.underscore.min.js)
+
+* CDN copies of â€ v1.0.1âs builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/):<br>
+[Lo-Dash dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.js),
+[Lo-Dash prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.min.js),<br>
+[Lo-Dash compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.js),
+[Lo-Dash compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.min.js),<br>
+[Underscore compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.js), and
+[Underscore compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.min.js)
+
+* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
+
+## Dive in
+
+Weâve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).
+
+For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
+
+## Resources
+
+For more information check out these articles, screencasts, and other videos over Lo-Dash:
+
+ * Posts
+  - [Say âHelloâ to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
+
+ * Videos
+  - [Introducing Lo-Dash](https://vimeo.com/44154599)
+  - [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
+  - [Lo-Dashâs origin and why itâs a better utility belt](https://vimeo.com/44154600)
+  - [Unit testing in Lo-Dash](https://vimeo.com/45865290)
+  - [Lo-Dashâs approach to native method use](https://vimeo.com/48576012)
+  - [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)
+
+## Features
+
+ * AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
+ * [_(âŠ)](http://lodash.com/docs#_) supports intuitive chaining
+ * [_.at](http://lodash.com/docs#at) for cherry-picking collection values
+ * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*âlazyâ* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods
+ * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects
+ * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument
+ * [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
+ * [_.forIn](http://lodash.com/docs#forIn) for iterating over an objectâs own and inherited properties
+ * [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objectâs own properties
+ * [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
+ * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
+ * [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding
+ * [_.template](http://lodash.com/docs#template) supports [*âimportsâ* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+ * [_.where](http://lodash.com/docs#where) supports deep object comparisons
+ * [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick),
+   [and moreâŠ](http://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments
+ * [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
+   [and moreâŠ](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings
+ * [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map),
+   [and moreâŠ](http://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *â_.pluckâ* and *â_.whereâ* `callback` shorthands
+
+## Support
+
+Lo-Dash has been tested in at least Chrome 5~24, Firefox 1~18, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.20, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
+
+## Custom builds
+
+Custom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.
+To top it off, we handle all method dependency and alias mapping for you.
+
+ * Backbone builds, with only methods required by Backbone, may be created using the `backbone` modifier argument.
+```bash
+lodash backbone
+```
+
+ * CSP builds, supporting default [Content Security Policy](https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html) restrictions, may be created using the `csp` modifier argument.
+   The `csp` modifier is an alais of the `mobile` modifier. Lo-Dash may be used in Chrome extensions by using either the `csp`, `mobile`, or `underscore` build and using precompiled templates, or loading Lo-Dash in a [sandbox](http://developer.chrome.com/stable/extensions/sandboxingEval.html).
+```bash
+lodash csp
+```
+
+ * Legacy builds, tailored for older environments without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
+```bash
+lodash legacy
+```
+
+ * Modern builds, tailored for newer environments with ES5 support, may be created using the `modern` modifier argument.
+```bash
+lodash modern
+```
+
+ * Mobile builds, without method compilation and most bug fixes for old browsers, may be created using the `mobile` modifier argument.
+```bash
+lodash mobile
+```
+
+ * Strict builds, with `_.bindAll`, `_.defaults`, and `_.extend` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.
+```bash
+lodash strict
+```
+
+ * Underscore builds, tailored for projects already using Underscore, may be created using the `underscore` modifier argument.
+```bash
+lodash underscore
+```
+
+Custom builds may be created using the following commands:
+
+ * Use the `category` argument to pass comma separated categories of methods to include in the build.<br>
+   Valid categories (case-insensitive) are *âarraysâ*, *âchainingâ*, *âcollectionsâ*, *âfunctionsâ*, *âobjectsâ*, and *âutilitiesâ*.
+```bash
+lodash category=collections,functions
+lodash category="collections, functions"
+```
+
+ * Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.<br>
+   Valid exports are *âamdâ*, *âcommonjsâ*, *âglobalâ*, *ânodeâ*, and *ânoneâ*.
+```bash
+lodash exports=amd,commonjs,node
+lodash exports="amd, commonjs, node"
+```
+
+ * Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.
+```bash
+lodash iife="!function(window,undefined){%output%}(this)"
+```
+
+ * Use the `include` argument to pass comma separated method/category names to include in the build.
+```bash
+lodash include=each,filter,map
+lodash include="each, filter, map"
+```
+
+ * Use the `minus` argument to pass comma separated method/category names to remove from those included in the build.
+```bash
+lodash underscore minus=result,shuffle
+lodash underscore minus="result, shuffle"
+```
+
+ * Use the `plus` argument to pass comma separated method/category names to add to those included in the build.
+```bash
+lodash backbone plus=random,template
+lodash backbone plus="random, template"
+```
+
+ * Use the `template` argument to pass the file path pattern used to match template files to precompile.
+```bash
+lodash template="./*.jst"
+```
+
+ * Use the `settings` argument to pass the template settings used when precompiling templates.
+```bash
+lodash settings="{interpolate:/\{\{([\s\S]+?)\}\}/g}"
+```
+
+ * Use the `moduleId` argument to specify the AMD module ID of Lo-Dash, which defaults to âlodashâ, used by precompiled templates.
+```bash
+lodash moduleId="underscore"
+```
+
+All arguments, except `legacy` with `csp`, `mobile`, `modern`, or `underscore`, may be combined.<br>
+Unless specified by `-o` or `--output`, all files created are saved to the current working directory.
+
+The following options are also supported:
+
+ * `-c`, `--stdout` ......... Write output to standard output
+ * `-d`, `--debug` ........... Write only the non-minified development output
+ * `-h`, `--help` ............. Display help information
+ * `-m`, `--minify` ......... Write only the minified production output
+ * `-o`, `--output` ......... Write output to a given path/filename
+ * `-p`, `--source-map` .. Generate a source map for the minified output, using an optional source map URL
+ * `-s`, `--silent` ......... Skip status updates normally logged to the console
+ * `-V`, `--version` ....... Output current version of Lo-Dash
+
+The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
+
+## Installation and usage
+
+In browsers:
+
+```html
+<script src="lodash.js"></script>
+```
+
+Using [`npm`](http://npmjs.org/):
+
+```bash
+npm install lodash
+
+npm install -g lodash
+npm link lodash
+```
+
+To avoid potential issues, update `npm` before installing Lo-Dash:
+
+```bash
+npm install npm -g
+```
+
+In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
+
+```js
+var _ = require('lodash');
+
+// or as a drop-in replacement for Underscore
+var _ = require('lodash/lodash.underscore');
+```
+
+**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projectâs root directory before requiring it.
+
+In [RingoJS v0.7.0-](http://ringojs.org/):
+
+```js
+var _ = require('lodash')._;
+```
+
+In [Rhino](http://www.mozilla.org/rhino/):
+
+```js
+load('lodash.js');
+```
+
+In an AMD loader like [RequireJS](http://requirejs.org/):
+
+```js
+require({
+  'paths': {
+    'underscore': 'path/to/lodash'
+  }
+},
+['underscore'], function(_) {
+  console.log(_.VERSION);
+});
+```
+
+## Release Notes
+
+### <sup>v1.0.1</sup>
+
+ * Add support for specifying source map URLs in `-p`/`--source-map` build options
+ * Ensured the second argument passed to `_.assign` is not treated as a `callback`
+ * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL`
+ * Made `-p`/`--source-map` build options set source map *âsourcesâ* keys based on the builds performed
+ * Made `_.defer` use `setImmediate`, in Node.js, when available
+ * Made `_.where` search arrays for values regardless of their index position
+ * Removed dead code from `_.template`
+
+The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
+
+## BestieJS
+
+Lo-Dash is part of the BestieJS *âBest in Classâ* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
+
+## Author
+
+* [John-David Dalton](http://allyoucanleet.com/)
+  [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
+
+## Contributors
+
+* [Kit Cambridge](http://kitcambridge.github.com/)
+  [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
+* [Mathias Bynens](http://mathiasbynens.be/)
+  [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build.js	(revision 533)
@@ -0,0 +1,2509 @@
+#!/usr/bin/env node
+;(function() {
+  'use strict';
+
+  /** Load modules */
+  var fs = require('fs'),
+      path = require('path'),
+      vm = require('vm'),
+      minify = require(path.join(__dirname, 'build', 'minify.js')),
+      _ = require(path.join(__dirname, 'lodash.js'));
+
+  /** The current working directory */
+  var cwd = process.cwd();
+
+  /** Used for array method references */
+  var arrayRef = [];
+
+  /** Shortcut used to push arrays of values to an array */
+  var push = arrayRef.push;
+
+  /** Shortcut used to convert array-like objects to arrays */
+  var slice = arrayRef.slice;
+
+  /** Shortcut to the `stdout` object */
+  var stdout = process.stdout;
+
+  /** Used to associate aliases with their real names */
+  var aliasToRealMap = {
+    'all': 'every',
+    'any': 'some',
+    'collect': 'map',
+    'detect': 'find',
+    'drop': 'rest',
+    'each': 'forEach',
+    'extend': 'assign',
+    'foldl': 'reduce',
+    'foldr': 'reduceRight',
+    'head': 'first',
+    'include': 'contains',
+    'inject': 'reduce',
+    'methods': 'functions',
+    'select': 'filter',
+    'tail': 'rest',
+    'take': 'first',
+    'unique': 'uniq'
+  };
+
+  /** Used to associate real names with their aliases */
+  var realToAliasMap = {
+    'assign': ['extend'],
+    'contains': ['include'],
+    'every': ['all'],
+    'filter': ['select'],
+    'find': ['detect'],
+    'first': ['head', 'take'],
+    'forEach': ['each'],
+    'functions': ['methods'],
+    'map': ['collect'],
+    'reduce': ['foldl', 'inject'],
+    'reduceRight': ['foldr'],
+    'rest': ['drop', 'tail'],
+    'some': ['any'],
+    'uniq': ['unique']
+  };
+
+  /** Used to track function dependencies */
+  var dependencyMap = {
+    'after': [],
+    'assign': ['isArray', 'forEach', 'forOwn'],
+    'at': ['isString'],
+    'bind': ['isFunction', 'isObject'],
+    'bindAll': ['bind', 'functions'],
+    'bindKey': ['isFunction', 'isObject'],
+    'clone': ['assign', 'forEach', 'forOwn', 'isArray', 'isObject'],
+    'cloneDeep': ['clone'],
+    'compact': [],
+    'compose': [],
+    'contains': ['indexOf', 'isString'],
+    'countBy': ['forEach', 'identity', 'isEqual', 'keys'],
+    'debounce': [],
+    'defaults': ['isArray', 'forEach', 'forOwn'],
+    'defer': ['bind'],
+    'delay': [],
+    'difference': ['indexOf'],
+    'escape': [],
+    'every': ['identity', 'isArray', 'isEqual', 'keys'],
+    'filter': ['identity', 'isArray', 'isEqual', 'keys'],
+    'find': ['forEach', 'identity', 'isEqual', 'keys'],
+    'first': [],
+    'flatten': ['isArray'],
+    'forEach': ['identity', 'isArguments', 'isArray', 'isString'],
+    'forIn': ['identity', 'isArguments'],
+    'forOwn': ['identity', 'isArguments'],
+    'functions': ['forIn', 'isFunction'],
+    'groupBy': ['forEach', 'identity', 'isEqual', 'keys'],
+    'has': [],
+    'identity': [],
+    'indexOf': ['sortedIndex'],
+    'initial': [],
+    'intersection': ['indexOf'],
+    'invert': ['keys'],
+    'invoke': ['forEach'],
+    'isArguments': [],
+    'isArray': [],
+    'isBoolean': [],
+    'isDate': [],
+    'isElement': [],
+    'isEmpty': ['forOwn', 'isArguments', 'isFunction'],
+    'isEqual': ['forIn', 'isArguments', 'isFunction'],
+    'isFinite': [],
+    'isFunction': [],
+    'isNaN': ['isNumber'],
+    'isNull': [],
+    'isNumber': [],
+    'isObject': [],
+    'isPlainObject': ['forIn', 'isArguments', 'isFunction'],
+    'isRegExp': [],
+    'isString': [],
+    'isUndefined': [],
+    'keys': ['forOwn', 'isArguments', 'isObject'],
+    'last': [],
+    'lastIndexOf': [],
+    'map': ['identity', 'isArray', 'isEqual', 'keys'],
+    'max': ['isArray', 'isEqual', 'isString', 'keys'],
+    'memoize': [],
+    'merge': ['forEach', 'forOwn', 'isArray', 'isObject', 'isPlainObject'],
+    'min': ['isArray', 'isEqual', 'isString', 'keys'],
+    'mixin': ['forEach', 'forOwn', 'functions'],
+    'noConflict': [],
+    'object': [],
+    'omit': ['forIn', 'indexOf'],
+    'once': [],
+    'pairs': ['keys'],
+    'partial': ['isFunction', 'isObject'],
+    'partialRight': ['isFunction', 'isObject'],
+    'pick': ['forIn', 'isObject'],
+    'pluck': ['map'],
+    'random': [],
+    'range': [],
+    'reduce': ['identity', 'isArray', 'isEqual', 'keys'],
+    'reduceRight': ['forEach', 'identity', 'isEqual', 'isString', 'keys'],
+    'reject': ['filter', 'identity', 'isEqual', 'keys'],
+    'rest': [],
+    'result': ['isFunction'],
+    'shuffle': ['forEach'],
+    'size': ['keys'],
+    'some': ['identity', 'isArray', 'isEqual', 'keys'],
+    'sortBy': ['forEach', 'identity', 'isEqual', 'keys'],
+    'sortedIndex': ['identity', 'isEqual', 'keys'],
+    'tap': ['mixin'],
+    'template': ['defaults', 'escape', 'keys', 'values'],
+    'throttle': [],
+    'times': [],
+    'toArray': ['isString', 'values'],
+    'unescape': [],
+    'union': ['uniq'],
+    'uniq': ['indexOf', 'isEqual', 'keys'],
+    'uniqueId': [],
+    'value': ['mixin'],
+    'values': ['keys'],
+    'where': ['filter'],
+    'without': ['indexOf'],
+    'wrap': [],
+    'zip': ['max', 'pluck'],
+
+    // method used by the `backbone` and `underscore` builds
+    'chain': ['mixin'],
+    'findWhere': ['where']
+  };
+
+  /** Used to inline `iteratorTemplate` */
+  var iteratorOptions = [
+    'args',
+    'arrays',
+    'bottom',
+    'firstArg',
+    'hasDontEnumBug',
+    'hasEnumPrototype',
+    'isKeysFast',
+    'loop',
+    'nonEnumArgs',
+    'noCharByIndex',
+    'shadowed',
+    'top',
+    'useHas'
+  ];
+
+  /** List of all Lo-Dash methods */
+  var allMethods = _.keys(dependencyMap);
+
+  /** List of Backbone's Lo-Dash dependencies */
+  var backboneDependencies = [
+    'bind',
+    'bindAll',
+    'chain',
+    'clone',
+    'contains',
+    'countBy',
+    'defaults',
+    'escape',
+    'every',
+    'extend',
+    'filter',
+    'find',
+    'first',
+    'forEach',
+    'groupBy',
+    'has',
+    'indexOf',
+    'initial',
+    'invoke',
+    'isArray',
+    'isEmpty',
+    'isEqual',
+    'isFunction',
+    'isObject',
+    'isRegExp',
+    'isString',
+    'keys',
+    'last',
+    'lastIndexOf',
+    'map',
+    'max',
+    'min',
+    'mixin',
+    'once',
+    'pick',
+    'reduce',
+    'reduceRight',
+    'reject',
+    'rest',
+    'result',
+    'shuffle',
+    'size',
+    'some',
+    'sortBy',
+    'sortedIndex',
+    'toArray',
+    'uniqueId',
+    'value',
+    'without'
+  ];
+
+  /** List of methods used by Underscore */
+  var underscoreMethods = _.without.apply(_, [allMethods].concat([
+    'at',
+    'bindKey',
+    'cloneDeep',
+    'forIn',
+    'forOwn',
+    'isPlainObject',
+    'merge',
+    'partialRight'
+  ]));
+
+  /** List of ways to export the `lodash` function */
+  var exportsAll = [
+    'amd',
+    'commonjs',
+    'global',
+    'node'
+  ];
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Adds support for Underscore style chaining to the `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function addChainMethods(source) {
+    // add `_.chain`
+    source = source.replace(matchFunction(source, 'tap'), function(match) {
+      return [
+        '',
+        '  /**',
+        '   * Creates a `lodash` object that wraps the given `value`.',
+        '   *',
+        '   * @static',
+        '   * @memberOf _',
+        '   * @category Chaining',
+        '   * @param {Mixed} value The value to wrap.',
+        '   * @returns {Object} Returns the wrapper object.',
+        '   * @example',
+        '   *',
+        '   * var stooges = [',
+        "   *   { 'name': 'moe', 'age': 40 },",
+        "   *   { 'name': 'larry', 'age': 50 },",
+        "   *   { 'name': 'curly', 'age': 60 }",
+        '   * ];',
+        '   *',
+        '   * var youngest = _.chain(stooges)',
+        '   *     .sortBy(function(stooge) { return stooge.age; })',
+        "   *     .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })",
+        '   *     .first();',
+        "   * // => 'moe is 40'",
+        '   */',
+        '  function chain(value) {',
+        '    value = new lodash(value);',
+        '    value.__chain__ = true;',
+        '    return value;',
+        '  }',
+        '',
+        match
+      ].join('\n');
+    });
+
+    // add `wrapperChain`
+    source = source.replace(matchFunction(source, 'wrapperToString'), function(match) {
+      return [
+        '',
+        '  /**',
+        '   * Enables method chaining on the wrapper object.',
+        '   *',
+        '   * @name chain',
+        '   * @memberOf _',
+        '   * @category Chaining',
+        '   * @returns {Mixed} Returns the wrapper object.',
+        '   * @example',
+        '   *',
+        '   * var sum = _([1, 2, 3])',
+        '   *     .chain()',
+        '   *     .reduce(function(sum, num) { return sum + num; })',
+        '   *     .value()',
+        '   * // => 6`',
+        '   */',
+        '  function wrapperChain() {',
+        '    this.__chain__ = true;',
+        '    return this;',
+        '  }',
+        '',
+        match
+      ].join('\n');
+    });
+
+    // add `lodash.chain` assignment
+    source = source.replace(getMethodAssignments(source), function(match) {
+      return match.replace(/^(?: *\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\n)?( *)lodash\.VERSION *=/m, '$1lodash.chain = chain;\n\n$&');
+    });
+
+    // add `lodash.prototype.chain` assignment
+    source = source.replace(/^( *)lodash\.prototype\.value *=.+\n/m, '$1lodash.prototype.chain = wrapperChain;\n$&');
+
+    // remove `lodash.prototype.toString` and `lodash.prototype.valueOf` assignments
+    source = source.replace(/^ *lodash\.prototype\.(?:toString|valueOf) *=.+\n/gm, '');
+
+    // remove `lodash.prototype` batch method assignments
+    source = source.replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, '');
+
+    // move `mixin(lodash)` to after the method assignments
+    source = source.replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+/, '');
+    source = source.replace(getMethodAssignments(source), function(match) {
+      return match + [
+        '',
+        '',
+        '  // add functions to `lodash.prototype`',
+        '  mixin(lodash);'
+      ].join('\n');
+    });
+
+    // add `__chain__` checks to `_.mixin`
+    source = source.replace(matchFunction(source, 'mixin'), function(match) {
+      return match.replace(/^( *)return new lodash.+/m, function() {
+        var indent = arguments[1];
+        return indent + [
+          '',
+          'var result = func.apply(lodash, args);',
+          'if (this.__chain__) {',
+          '  result = new lodash(result);',
+          '  result.__chain__ = true;',
+          '}',
+          'return result;'
+        ].join('\n' + indent);
+      });
+    });
+
+    // replace wrapper `Array` method assignments
+    source = source.replace(/^(?: *\/\/.*\n)*( *)each\(\['[\s\S]+?\n\1}$/m, function() {
+      return [
+        '  // add `Array` mutator functions to the wrapper',
+        "  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {",
+        '    var func = arrayRef[methodName];',
+        '    lodash.prototype[methodName] = function() {',
+        '      var value = this.__wrapped__;',
+        '      func.apply(value, arguments);',
+        '',
+        '      // avoid array-like object bugs with `Array#shift` and `Array#splice`',
+        '      // in Firefox < 10 and IE < 9',
+        '      if (hasObjectSpliceBug && value.length === 0) {',
+        '        delete value[0];',
+        '      }',
+        '      return this;',
+        '    };',
+        '  });',
+        '',
+        '  // add `Array` accessor functions to the wrapper',
+        "  each(['concat', 'join', 'slice'], function(methodName) {",
+        '    var func = arrayRef[methodName];',
+        '    lodash.prototype[methodName] = function() {',
+        '      var value = this.__wrapped__,',
+        '          result = func.apply(value, arguments);',
+        '',
+        '      if (this.__chain__) {',
+        '        result = new lodash(result);',
+        '        result.__chain__ = true;',
+        '      }',
+        '      return result;',
+        '    };',
+        '  });'
+      ].join('\n');
+    });
+
+    return source;
+  }
+
+  /**
+   * Adds build `commands` to the copyright/license header of the `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @param {Array} [commands=[]] An array of commands.
+   * @returns {String} Returns the modified source.
+   */
+  function addCommandsToHeader(source, commands) {
+    return source.replace(/(\/\**\n)( \*)( *@license[\s*]+)( *Lo-Dash [\w.-]+)(.*)/, function() {
+      // remove `node path/to/build.js` from `commands`
+      if (commands[0] == 'node') {
+        commands.splice(0, 2);
+      }
+      // add quotes to commands with spaces or equals signs
+      commands = _.map(commands, function(command) {
+        var separator = (command.match(/[= ]/) || [''])[0];
+        if (separator) {
+          var pair = command.split(separator);
+          command = pair[0] + separator + '"' + pair[1] + '"';
+        }
+        // escape newlines, carriage returns, multi-line comment end tokens
+        command = command
+          .replace(/\n/g, '\\n')
+          .replace(/\r/g, '\\r')
+          .replace(/\*\//g, '*\\/');
+
+        return command;
+      });
+      // add build commands to copyright/license header
+      var parts = slice.call(arguments, 1);
+      return (
+        parts[0] +
+        parts[1] +
+        parts[2] + parts[3] + ' (Custom Build)' + parts[4] + '\n' +
+        parts[1] + ' Build: `lodash ' + commands.join(' ') + '`'
+      );
+    });
+  }
+
+  /**
+   * Compiles template files matched by the given file path `pattern` into a
+   * single source, extending `_.templates` with precompiled templates named after
+   * each template file's basename.
+   *
+   * @private
+   * @param {String} [pattern='<cwd>/*.jst'] The file path pattern.
+   * @param {Object} options The options object.
+   * @returns {String} Returns the compiled source.
+   */
+  function buildTemplate(pattern, options) {
+    pattern || (pattern = path.join(cwd, '*.jst'));
+
+    var directory = path.dirname(pattern);
+
+    var source = [
+      ';(function(window) {',
+      "  var freeExports = typeof exports == 'object' && exports;",
+      '',
+      "  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;",
+      '',
+      "  var freeGlobal = typeof global == 'object' && global;",
+      '  if (freeGlobal.global === freeGlobal) {',
+      '    window = freeGlobal;',
+      '  }',
+      '',
+      '  var templates = {},',
+      '      _ = window._;',
+      ''
+    ];
+
+    // convert to a regexp
+    pattern = RegExp(
+      path.basename(pattern)
+        .replace(/[.+?^=!:${}()|[\]\/\\]/g, '\\$&')
+        .replace(/\*/g, '.*?') + '$'
+    );
+
+    fs.readdirSync(directory).forEach(function(filename) {
+      var filePath = path.join(directory, filename);
+      if (pattern.test(filename)) {
+        var text = fs.readFileSync(filePath, 'utf8'),
+            precompiled = getFunctionSource(_.template(text, null, options)),
+            prop = filename.replace(/\..*$/, '');
+
+        source.push("  templates['" + prop.replace(/['\n\r\t]/g, '\\$&') + "'] = " + precompiled + ';', '');
+      }
+    });
+
+    source.push(
+      "  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {",
+      "    define(['" + options.moduleId + "'], function(lodash) {",
+      '      _ = lodash;',
+      '      lodash.templates = lodash.extend(lodash.templates || {}, templates);',
+      '    });',
+      "  } else if (freeExports) {",
+      "    if (freeModule) {",
+      '      (freeModule.exports = templates).templates = templates;',
+      '    } else {',
+      '      freeExports.templates = templates;',
+      '    }',
+      '  } else if (_) {',
+      '    _.templates = _.extend(_.templates || {}, templates);',
+      '  }',
+      '}(this));'
+    );
+
+    return source.join('\n');
+  }
+
+  /**
+   * Capitalizes a given string.
+   *
+   * @private
+   * @param {String} string The string to capitalize.
+   * @returns {String} Returns the capitalized string.
+   */
+  function capitalize(string) {
+    return string[0].toUpperCase() + string.toLowerCase().slice(1);
+  }
+
+  /**
+   * Removes unnecessary comments, whitespace, and pseudo private properties.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function cleanupSource(source) {
+    return source
+      // remove pseudo private properties
+      .replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n')
+      // remove lines with just whitespace and semicolons
+      .replace(/^ *;\n/gm, '')
+      // consolidate multiple newlines
+      .replace(/\n{3,}/g, '\n\n')
+      // consolidate consecutive horizontal rule comment separators
+      .replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
+        return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
+      });
+  }
+
+  /**
+   * Writes the help message to standard output.
+   *
+   * @private
+   */
+  function displayHelp() {
+    console.log([
+      '',
+      '  Commands:',
+      '',
+      '    lodash backbone      Build with only methods required by Backbone',
+      '    lodash csp           Build supporting default Content Security Policy restrictions',
+      '    lodash legacy        Build tailored for older environments without ES5 support',
+      '    lodash modern        Build tailored for newer environments with ES5 support',
+      '    lodash mobile        Build without method compilation and most bug fixes for old browsers',
+      '    lodash strict        Build with `_.assign`, `_.bindAll`, & `_.defaults` in strict mode',
+      '    lodash underscore    Build tailored for projects already using Underscore',
+      '    lodash include=...   Comma separated method/category names to include in the build',
+      '    lodash minus=...     Comma separated method/category names to remove from those included in the build',
+      '    lodash plus=...      Comma separated method/category names to add to those included in the build',
+      '    lodash category=...  Comma separated categories of methods to include in the build (case-insensitive)',
+      '                         (i.e. âarraysâ, âchainingâ, âcollectionsâ, âfunctionsâ, âobjectsâ, and âutilitiesâ)',
+      '    lodash exports=...   Comma separated names of ways to export the `lodash` function',
+      '                         (i.e. âamdâ, âcommonjsâ, âglobalâ, ânodeâ, and ânoneâ)',
+      '    lodash iife=...      Code to replace the immediately-invoked function expression that wraps Lo-Dash',
+      '                         (e.g. `lodash iife="!function(window,undefined){%output%}(this)"`)',
+      '',
+      '    lodash template=...  File path pattern used to match template files to precompile',
+      '                         (e.g. `lodash template=./*.jst`)',
+      '    lodash settings=...  Template settings used when precompiling templates',
+      '                         (e.g. `lodash settings="{interpolate:/{{([\\s\\S]+?)}}/g}"`)',
+      '    lodash moduleId=...  The AMD module ID of Lo-Dash, which defaults to âlodashâ, used by precompiled templates',
+      '',
+      '    All arguments, except `legacy` with `csp`, `mobile`, `modern`, or `underscore`, may be combined.',
+      '    Unless specified by `-o` or `--output`, all files created are saved to the current working directory.',
+      '',
+      '  Options:',
+      '',
+      '    -c, --stdout      Write output to standard output',
+      '    -d, --debug       Write only the non-minified development output',
+      '    -h, --help        Display help information',
+      '    -m, --minify      Write only the minified production output',
+      '    -o, --output      Write output to a given path/filename',
+      '    -p, --source-map  Generate a source map for the minified output, using an optional source map URL',
+      '    -s, --silent      Skip status updates normally logged to the console',
+      '    -V, --version     Output current version of Lo-Dash',
+      ''
+    ].join('\n'));
+  }
+
+  /**
+   * Gets the aliases associated with a given function name.
+   *
+   * @private
+   * @param {String} methodName The name of the method to get aliases for.
+   * @returns {Array} Returns an array of aliases.
+   */
+  function getAliases(methodName) {
+    return realToAliasMap[methodName] || [];
+  }
+
+  /**
+   * Gets the category of the given method name.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} methodName The method name.
+   * @returns {String} Returns the method name's category.
+   */
+  function getCategory(source, methodName) {
+    var result = /@category +(\w+)/.exec(matchFunction(source, methodName));
+    return result ? result[1] : '';
+  }
+
+  /**
+   * Gets an array of category dependencies for a given category.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} category The category.
+   * @returns {Array} Returns an array of cetegory dependants.
+   */
+  function getCategoryDependencies(source, category) {
+    var methods = _.uniq(getMethodsByCategory(source, category).reduce(function(result, methodName) {
+      push.apply(result, getDependencies(methodName));
+      return result;
+    }, []));
+
+    var categories = _.uniq(methods.map(function(methodName) {
+      return getCategory(source, methodName);
+    }));
+
+    return categories.filter(function(other) {
+      return other != category;
+    });
+  }
+
+  /**
+   * Gets an array of depenants for a method by a given name.
+   *
+   * @private
+   * @param {String} methodName The method name.
+   * @returns {Array} Returns an array of method dependants.
+   */
+  function getDependants(methodName) {
+    // iterate over the `dependencyMap`, adding the names of methods that
+    // have `methodName` as a dependency
+    return _.reduce(dependencyMap, function(result, dependencies, otherName) {
+      if (_.contains(dependencies, methodName)) {
+        result.push(otherName);
+      }
+      return result;
+    }, []);
+  }
+
+  /**
+   * Gets an array of dependencies for a given method name. If passed an array
+   * of dependencies it will return an array containing the given dependencies
+   * plus any additional detected sub-dependencies.
+   *
+   * @private
+   * @param {Array|String} methodName A single method name or array of
+   *  dependencies to query.
+   * @returns {Array} Returns an array of method dependencies.
+   */
+  function getDependencies(methodName) {
+    var dependencies = Array.isArray(methodName) ? methodName : dependencyMap[methodName];
+    if (!dependencies) {
+      return [];
+    }
+    // recursively accumulate the dependencies of the `methodName` function, and
+    // the dependencies of its dependencies, and so on
+    return _.uniq(dependencies.reduce(function(result, otherName) {
+      result.push.apply(result, getDependencies(otherName).concat(otherName));
+      return result;
+    }, []));
+  }
+
+  /**
+   * Gets the formatted source of the given function.
+   *
+   * @private
+   * @param {Function} func The function to process.
+   * @returns {String} Returns the formatted source.
+   */
+  function getFunctionSource(func) {
+    var source = func.source || (func + '');
+
+    // format leading whitespace
+    return source.replace(/\n(?:.*)/g, function(match, index) {
+      match = match.slice(1);
+      return (
+        match == '}' && source.indexOf('}', index + 2) < 0 ? '\n  ' : '\n    '
+      ) + match;
+    });
+  }
+
+  /**
+   * Gets the `_.isArguments` fallback from `source`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @returns {String} Returns the `isArguments` fallback.
+   */
+  function getIsArgumentsFallback(source) {
+    return (source.match(/(?:\s*\/\/.*)*\n( *)if *\((?:noArgsClass|!isArguments)[\s\S]+?};\n\1}/) || [''])[0];
+  }
+
+  /**
+   * Gets the `_.isFunction` fallback from `source`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @returns {String} Returns the `isFunction` fallback.
+   */
+  function getIsFunctionFallback(source) {
+    return (source.match(/(?:\s*\/\/.*)*\n( *)if *\(isFunction\(\/x\/[\s\S]+?};\n\1}/) || [''])[0];
+  }
+
+  /**
+   * Gets the `iteratorTemplate` from `source`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @returns {String} Returns the `iteratorTemplate`.
+   */
+  function getIteratorTemplate(source) {
+    return (source.match(/^( *)var iteratorTemplate *= *[\s\S]+?\n\1.+?;\n/m) || [''])[0];
+  }
+
+  /**
+   * Gets the Lo-Dash method assignments snippet from `source`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @returns {String} Returns the method assignments snippet.
+   */
+  function getMethodAssignments(source) {
+    return (source.match(/\/\*-+\*\/\n(?:\s*\/\/.*)*\s*lodash\.\w+ *=[\s\S]+?lodash\.VERSION *=.+/) || [''])[0];
+  }
+
+  /**
+   * Gets the names of methods in `source` belonging to the given `category`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} category The category to filter by.
+   * @returns {Array} Returns a new array of method names belonging to the given category.
+   */
+  function getMethodsByCategory(source, category) {
+    return allMethods.filter(function(methodName) {
+      return getCategory(source, methodName) == category;
+    });
+  }
+
+  /**
+   * Gets the real name, not alias, of a given method name.
+   *
+   * @private
+   * @param {String} methodName The name of the method to resolve.
+   * @returns {String} Returns the real method name.
+   */
+  function getRealName(methodName) {
+    return aliasToRealMap[methodName] || methodName;
+  }
+
+  /**
+   * Determines if all functions of the given names have been removed from `source`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} [funcName1, funcName2, ...] The names of functions to check.
+   * @returns {Boolean} Returns `true` if all functions have been removed, else `false`.
+   */
+  function isRemoved(source) {
+    return slice.call(arguments, 1).every(function(funcName) {
+      return !matchFunction(source, funcName);
+    });
+  }
+
+  /**
+   * Searches `source` for a `funcName` function declaration, expression, or
+   * assignment and returns the matched snippet.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} funcName The name of the function to match.
+   * @returns {String} Returns the matched function snippet.
+   */
+  function matchFunction(source, funcName) {
+    var result = source.match(RegExp(
+      // match multi-line comment block (could be on a single line)
+      '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/\\n)?' +
+      // begin non-capturing group
+      '( *)(?:' +
+      // match a function declaration
+      'function ' + funcName + '\\b[\\s\\S]+?\\n\\1}|' +
+      // match a variable declaration with function expression
+      'var ' + funcName + ' *=.*?function[\\s\\S]+?\\n\\1};' +
+      // end non-capturing group
+      ')\\n'
+    ));
+
+    // match variables that are explicitly defined as functions
+    result || (result = source.match(RegExp(
+      // match multi-line comment block
+      '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)?\\n' +
+      // match simple variable declarations and those with `createIterator`
+      ' *var ' + funcName + ' *=(?:.+?|.*?createIterator\\([\\s\\S]+?\\));\\n'
+    )));
+
+    return /@type +Function|function\s*\w*\(/.test(result) ? result[0] : '';
+  }
+
+  /**
+   * Converts a comma separated options string into an array.
+   *
+   * @private
+   * @param {String} value The option to convert.
+   * @returns {Array} Returns the new converted array.
+   */
+  function optionToArray(value) {
+    return value.match(/\w+=(.*)$/)[1].split(/, */);
+  }
+
+  /**
+   * Converts a comma separated options string into an array containing
+   * only real method names.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} value The option to convert.
+   * @returns {Array} Returns the new converted array.
+   */
+  function optionToMethodsArray(source, value) {
+    var methodNames = optionToArray(value);
+
+    // convert categories to method names
+    methodNames.forEach(function(category) {
+      push.apply(methodNames, getMethodsByCategory(source, category));
+    });
+
+    // convert aliases to real method names
+    methodNames = methodNames.map(getRealName);
+
+    // remove nonexistent and duplicate method names
+    return _.uniq(_.intersection(allMethods, methodNames));
+  }
+
+  /**
+   * Removes all `argsAreObjects` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeArgsAreObjects(source) {
+    source = removeVar(source, 'argsAreObjects');
+
+    // remove `argsAreObjects` from `_.isArray`
+    source = source.replace(matchFunction(source, 'isArray'), function(match) {
+      return match.replace(/\(argsAreObjects && *([^)]+)\)/g, '$1');
+    });
+
+    // remove `argsAreObjects` from `_.isEqual`
+    source = source.replace(matchFunction(source, 'isEqual'), function(match) {
+      return match.replace(/!argsAreObjects[^:]+:\s*/g, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes the all references to `varName` from `createIterator` in `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @param {String} varName The name of the variable to remove.
+   * @returns {String} Returns the modified source.
+   */
+  function removeFromCreateIterator(source, varName) {
+    var  snippet = matchFunction(source, 'createIterator');
+    if ( snippet) {
+       // remove data object property assignment
+      var modified = snippet.replace(RegExp("^ *'" + varName + "': *" + varName + '.+\\n', 'm'), '');
+      source = source.replace(snippet, modified);
+
+      // clip at the `factory` assignment
+      snippet = modified.match(/Function\([\s\S]+$/)[0];
+
+      modified = snippet
+        .replace(RegExp('\\b' + varName + '\\b,? *', 'g'), '')
+        .replace(/, *',/, "',")
+        .replace(/,\s*\)/, ')')
+
+      source = source.replace(snippet, modified);
+    }
+    return source;
+  }
+
+  /**
+   * Removes the `funcName` function declaration, expression, or assignment and
+   * associated code from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @param {String} funcName The name of the function to remove.
+   * @returns {String} Returns the modified source.
+   */
+  function removeFunction(source, funcName) {
+    // remove function
+    var snippet = matchFunction(source, funcName);
+    if (snippet) {
+      source = source.replace(snippet, '');
+    }
+    // grab the method assignments snippet
+    snippet = getMethodAssignments(source);
+
+    // remove assignment and aliases
+    var modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) {
+      return result.replace(RegExp('(?:\\n *//.*\\s*)* *lodash\\.' + otherName + ' *= *.+\\n'), '');
+    }, snippet);
+
+    // replace with the modified snippet
+    source = source.replace(snippet, modified);
+
+    return removeFromCreateIterator(source, funcName);
+  }
+
+  /**
+   * Removes all `hasDontEnumBug` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeHasDontEnumBug(source) {
+    source = removeFromCreateIterator(source, 'hasDontEnumBug');
+    source = removeFromCreateIterator(source, 'shadowed');
+
+    // remove `hasDontEnumBug` declaration and assignment
+    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b.*|.+?hasDontEnumBug *=.+/g, '');
+
+    // remove `shadowed` variable
+    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var shadowed[\s\S]+?;\n/, '');
+
+    // remove `hasDontEnumBug` from `iteratorTemplate`
+    source = source.replace(getIteratorTemplate(source), function(match) {
+      return match.replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(hasDontEnumBug[\s\S]+?["']\1<% *} *%>.+/, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes all `hasEnumPrototype` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeHasEnumPrototype(source) {
+    source = removeFromCreateIterator(source, 'hasEnumPrototype');
+
+    // remove `hasEnumPrototype` declaration and assignment
+    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasEnumPrototype\b.*|.+?hasEnumPrototype *=.+/g, '');
+
+    // remove `hasEnumPrototype` from `_.keys`
+    source = source.replace(matchFunction(source, 'keys'), function(match) {
+      return match
+        .replace(/\(hasEnumPrototype[^)]+\)(?:\s*\|\|\s*)?/, '')
+        .replace(/\s*if *\(\s*\)[^}]+}/, '');
+    });
+
+    // remove `hasEnumPrototype` from `iteratorTemplate`
+    source = source.replace(getIteratorTemplate(source), function(match) {
+      return match
+        .replace(/(?: *\/\/.*\n)* *["'] *(?:<% *)?if *\(hasEnumPrototype *(?:&&|\))[\s\S]+?<% *} *(?:%>|["']).+/g, '')
+        .replace(/hasEnumPrototype *\|\|\s*/g, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes the `_.isArguments` fallback from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeIsArgumentsFallback(source) {
+    return source.replace(getIsArgumentsFallback(source), '');
+  }
+
+  /**
+   * Removes the `_.isFunction` fallback from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeIsFunctionFallback(source) {
+    return source.replace(getIsFunctionFallback(source), '');
+  }
+
+  /**
+   * Removes all `iteratesOwnLast` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeIteratesOwnLast(source) {
+    // remove `iteratesOwnLast` declaration and assignment
+    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var iteratesOwnLast\b.*|.+?iteratesOwnLast *=.+/g, '');
+
+    // remove `iteratesOwnLast` from `shimIsPlainObject`
+    source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) {
+      return match.replace(/(?:\s*\/\/.*)*\n( *)if *\(iteratesOwnLast[\s\S]+?\n\1}/, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes the `Object.keys` object iteration optimization from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeKeysOptimization(source) {
+    source = removeVar(source, 'isKeysFast');
+
+    // remove optimized branch in `iteratorTemplate`
+    source = source.replace(getIteratorTemplate(source), function(match) {
+      return match.replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(isKeysFast[\s\S]+?["']\1<% *} *else *{ *%>.+\n([\s\S]+?) *["']\1<% *} *%>.+/, "'\\n' +\n$2");
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes all `noArgsClass` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeNoArgsClass(source) {
+    source = removeVar(source, 'noArgsClass');
+
+    // replace `noArgsClass` in the `_.isArguments` fallback
+    source = source.replace(getIsArgumentsFallback(source), function(match) {
+      return match.replace(/noArgsClass/g, '!isArguments(arguments)');
+    });
+
+    // remove `noArgsClass` from `_.isEmpty`
+    source = source.replace(matchFunction(source, 'isEmpty'), function(match) {
+      return match.replace(/ *\|\|\s*\(noArgsClass *&&[^)]+?\)\)/g, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes all `noCharByIndex` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeNoCharByIndex(source) {
+    source = removeVar(source, 'noCharByIndex');
+
+    // remove `noCharByIndex` from `_.at`
+    source = source.replace(matchFunction(source, 'at'), function(match) {
+      return match.replace(/^ *if *\(noCharByIndex[^}]+}\n/m, '');
+    });
+
+    // remove `noCharByIndex` from `_.reduceRight`
+    source = source.replace(matchFunction(source, 'reduceRight'), function(match) {
+      return match.replace(/}\s*else if *\(noCharByIndex[^}]+/, '');
+    });
+
+    // remove `noCharByIndex` from `_.toArray`
+    source = source.replace(matchFunction(source, 'toArray'), function(match) {
+      return match.replace(/noCharByIndex[^:]+:/, '');
+    });
+
+    // `noCharByIndex` from `iteratorTemplate`
+    source = source.replace(getIteratorTemplate(source), function(match) {
+      return match
+        .replace(/'if *\(<%= *arrays *%>[^']*/, '$&\\n')
+        .replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(noCharByIndex[\s\S]+?["']\1<% *} *%>.+/, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes all `nonEnumArgs` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeNonEnumArgs(source) {
+    source = removeFromCreateIterator(source, 'nonEnumArgs');
+
+    // remove `nonEnumArgs` declaration and assignment
+    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var nonEnumArgs\b.*|.+?nonEnumArgs *=.+/g, '');
+
+    // remove `nonEnumArgs` from `_.keys`
+    source = source.replace(matchFunction(source, 'keys'), function(match) {
+      return match
+        .replace(/(?:\s*\|\|\s*)?\(nonEnumArgs[^)]+\)\)/, '')
+        .replace(/\s*if *\(\s*\)[^}]+}/, '');
+    });
+
+    // remove `nonEnumArgs` from `iteratorTemplate`
+    source = source.replace(getIteratorTemplate(source), function(match) {
+      return match
+        .replace(/(?: *\/\/.*\n)*( *["'] *)<% *} *else *if *\(nonEnumArgs[\s\S]+?(\1<% *} *%>.+)/, '$2')
+        .replace(/ *\|\|\s*nonEnumArgs/, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes all `noNodeClass` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeNoNodeClass(source) {
+    // remove `noNodeClass` assignment
+    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *{(?:\s*\/\/.*)*\n *var noNodeClass[\s\S]+?catch[^}]+}\n/, '');
+
+    // remove `noNodeClass` from `shimIsPlainObject`
+    source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) {
+      return match.replace(/ *&& *\(!noNodeClass[\s\S]+?\)\)/, '');
+    });
+
+    // remove `noNodeClass` from `_.clone`
+    source = source.replace(matchFunction(source, 'clone'), function(match) {
+      return match.replace(/ *\|\|\s*\(noNodeClass[\s\S]+?\)\)/, '');
+    });
+
+    // remove `noNodeClass` from `_.isEqual`
+    source = source.replace(matchFunction(source, 'isEqual'), function(match) {
+      return match.replace(/ *\|\|\s*\(noNodeClass[\s\S]+?\)\)\)/, '');
+    });
+
+    return source;
+  }
+
+  /**
+   * Removes all `hasObjectSpliceByg` references from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeHasObjectSpliceBug(source) {
+    return removeVar(source, 'hasObjectSpliceBug')
+      // remove `hasObjectSpliceBug` fix from the `Array` function mixins
+      .replace(/(?:\s*\/\/.*)*\n( *)if *\(hasObjectSpliceBug[\s\S]+?(?:{\s*}|\n\1})/, '');
+  }
+
+  /**
+   * Removes the `setImmediate` fork of `_.defer`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @returns {String} Returns the modified source.
+   */
+  function removeSetImmediate(source) {
+    return source.replace(/(?:\s*\/\/.*)*\n( *)if *\(isV8 *&& *freeModule[\s\S]+?\n\1}/, '');
+  }
+
+  /**
+   * Removes a given variable from `source`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @param {String} varName The name of the variable to remove.
+   * @returns {String} Returns the modified source.
+   */
+  function removeVar(source, varName) {
+    // simplify `cloneableClasses`, `ctorByClass`, or `hasObjectSpliceBug`
+    if (/^(?:cloneableClasses|ctorByClass|hasObjectSpliceBug)$/.test(varName)) {
+      source = source.replace(RegExp('(var ' + varName + ' *=)[\\s\\S]+?\\n\\n'), '$1=null;\n\n');
+    }
+    source = source.replace(RegExp(
+      // match multi-line comment block
+      '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)?\\n' +
+      // match a variable declaration that's not part of a declaration list
+      '( *)var ' + varName + ' *= *(?:.+?(?:;|&&\\n[^;]+;)|(?:\\w+\\(|{)[\\s\\S]+?\\n\\1.+?;)\\n|' +
+      // match a variable in a declaration list
+      '\\n +' + varName + ' *=.+?,'
+    ), '');
+
+    // remove a varaible at the start of a variable declaration list
+    source = source.replace(RegExp('(var +)' + varName + ' *=.+?,\\s+'), '$1');
+
+    // remove a variable at the end of a variable declaration list
+    source = source.replace(RegExp(',\\s*' + varName + ' *=.+?;'), ';');
+
+    return removeFromCreateIterator(source, varName);
+  }
+
+  /**
+   * Replaces the `funcName` function body in `source` with `funcValue`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} varName The name of the function to replace.
+   * @returns {String} Returns the modified source.
+   */
+  function replaceFunction(source, funcName, funcValue) {
+    var match = matchFunction(source, funcName);
+    if (match) {
+      // clip snippet after the JSDoc comment block
+      match = match.replace(/^\s*(?:\/\/.*|\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)\n/, '');
+      source = source.replace(match, function() {
+        return funcValue.trimRight() + '\n';
+      });
+    }
+    return source;
+  }
+
+  /**
+   * Replaces the `varName` variable declaration value in `source` with `varValue`.
+   *
+   * @private
+   * @param {String} source The source to inspect.
+   * @param {String} varName The name of the variable to replace.
+   * @returns {String} Returns the modified source.
+   */
+  function replaceVar(source, varName, varValue) {
+    // replace a variable that's not part of a declaration list
+    var result = source.replace(RegExp(
+      '(( *)var ' + varName + ' *= *)' +
+      '(?:.+?;|(?:Function\\(.+?|.*?[^,])\\n[\\s\\S]+?\\n\\2.+?;)\\n'
+    ), function(match, captured) {
+      return captured + varValue + ';\n';
+    });
+
+    if (source == result) {
+      // replace a varaible at the start or middle of a declaration list
+      result = source.replace(RegExp('((?:var|\\n) +' + varName + ' *=).+?,'), function(match, captured) {
+        return captured + ' ' + varValue + ',';
+      });
+    }
+    if (source == result) {
+      // replace a variable at the end of a variable declaration list
+      result = source.replace(RegExp('(,\\s*' + varName + ' *=).+?;'), function(match, captured) {
+        return captured + ' ' + varValue + ';';
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Hard-codes the `strict` template option value for `iteratorTemplate`.
+   *
+   * @private
+   * @param {String} source The source to process.
+   * @param {Boolean} value The value to set.
+   * @returns {String} Returns the modified source.
+   */
+  function setUseStrictOption(source, value) {
+    // inject or remove the "use strict" directive
+    source = source.replace(/^([\s\S]*?function[^{]+{)(?:\s*'use strict';)?/, '$1' + (value ? "\n  'use strict';" : ''));
+
+    // replace `strict` branch in `iteratorTemplate` with hard-coded option
+    source = source.replace(getIteratorTemplate(source), function(match) {
+      return match.replace(/(template\()(?:\s*"'use strict.+)?/, '$1' + (value ? '\n    "\'use strict\';\\n" +' : ''));
+    });
+
+    return source;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a debug and/or minified build, executing the `callback` for each.
+   * The `callback` is invoked with two arguments; (filePath, outputSource).
+   *
+   * Note: For a list of commands see `displayHelp()` or run `lodash --help`.
+   *
+   * @param {Array} [options=[]] An array of commands.
+   * @param {Function} callback The function called per build.
+   */
+  function build(options, callback) {
+    options || (options = []);
+
+    // the debug version of `source`
+    var debugSource;
+
+    // used to specify the source map URL
+    var sourceMapURL;
+
+    // used to report invalid command-line arguments
+    var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
+      if (/^(?:-o|--output)$/.test(options[index - 1]) ||
+          /^(?:category|exclude|exports|iife|include|moduleId|minus|plus|settings|template)=.*$/.test(value)) {
+        return true;
+      }
+      var result = [
+        'backbone',
+        'csp',
+        'legacy',
+        'mobile',
+        'modern',
+        'modularize',
+        'strict',
+        'underscore',
+        '-c', '--stdout',
+        '-d', '--debug',
+        '-h', '--help',
+        '-m', '--minify',
+        '-o', '--output',
+        '-p', '--source-map',
+        '-s', '--silent',
+        '-V', '--version'
+      ].indexOf(value) > -1;
+
+      if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
+        result = true;
+        sourceMapURL = value;
+      }
+      return result;
+    });
+
+    // report invalid arguments
+    if (invalidArgs.length) {
+      console.log(
+        '\n' +
+        'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
+        ' passed: ' + invalidArgs.join(', ')
+      );
+      displayHelp();
+      return;
+    }
+
+    // display help message
+    if (_.find(options, function(arg) {
+          return /^(?:-h|--help)$/.test(arg);
+        })) {
+      displayHelp();
+      return;
+    }
+
+    // display `lodash.VERSION`
+    if (_.find(options, function(arg) {
+          return /^(?:-V|--version)$/.test(arg);
+        })) {
+      console.log(_.VERSION);
+      return;
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    // backup `dependencyMap` to restore later
+    var dependencyBackup = _.cloneDeep(dependencyMap);
+
+    // used to specify a custom IIFE to wrap Lo-Dash
+    var iife = options.reduce(function(result, value) {
+      var match = value.match(/iife=(.*)/);
+      return match ? match[1] : result;
+    }, null);
+
+    // the path to the source file
+    var filePath = path.join(__dirname, 'lodash.js');
+
+    // flag to specify a Backbone build
+    var isBackbone = options.indexOf('backbone') > -1;
+
+    // flag to specify a Content Security Policy build
+    var isCSP = options.indexOf('csp') > -1 || options.indexOf('CSP') > -1;
+
+    // flag to specify only creating the debug build
+    var isDebug = options.indexOf('-d') > -1 || options.indexOf('--debug') > -1;
+
+    // flag to indicate that a custom IIFE was specified
+    var isIIFE = typeof iife == 'string';
+
+    // flag to specify creating a source map for the minified source
+    var isMapped = options.indexOf('-p') > -1 || options.indexOf('--source-map') > -1;
+
+    // flag to specify only creating the minified build
+    var isMinify = options.indexOf('-m') > -1 || options.indexOf('--minify') > -1;
+
+    // flag to specify a mobile build
+    var isMobile = isCSP || options.indexOf('mobile') > -1;
+
+    // flag to specify a modern build
+    var isModern = isMobile || options.indexOf('modern') > -1;
+
+    // flag to specify a modularize build
+    var isModularize = options.indexOf('modularize') > -1;
+
+    // flag to specify writing output to standard output
+    var isStdOut = options.indexOf('-c') > -1 || options.indexOf('--stdout') > -1;
+
+    // flag to specify skipping status updates normally logged to the console
+    var isSilent = isStdOut || options.indexOf('-s') > -1 || options.indexOf('--silent') > -1;
+
+    // flag to specify `_.assign`, `_.bindAll`, and `_.defaults` are
+    // constructed using the "use strict" directive
+    var isStrict = options.indexOf('strict') > -1;
+
+    // flag to specify an Underscore build
+    var isUnderscore = isBackbone || options.indexOf('underscore') > -1;
+
+    // flag to specify a legacy build
+    var isLegacy = !(isModern || isUnderscore) && options.indexOf('legacy') > -1;
+
+    // used to specify methods of specific categories
+    var categories = options.reduce(function(result, value) {
+      return /category/.test(value) ? optionToArray(value) : result;
+    }, []);
+
+    // used to specify the ways to export the `lodash` function
+    var exportsOptions = options.reduce(function(result, value) {
+      return /exports/.test(value) ? optionToArray(value).sort() : result;
+    }, isUnderscore
+      ? ['commonjs', 'global', 'node']
+      : exportsAll.slice()
+    );
+
+    // used to specify the AMD module ID of Lo-Dash used by precompiled templates
+    var moduleId = options.reduce(function(result, value) {
+      var match = value.match(/moduleId=(.*)/);
+      return match ? match[1] : result;
+    }, 'lodash');
+
+    // used to specify the output path for builds
+    var outputPath = options.reduce(function(result, value, index) {
+      if (/-o|--output/.test(value)) {
+        result = options[index + 1];
+        result = path.join(fs.realpathSync(path.dirname(result)), path.basename(result));
+      }
+      return result;
+    }, '');
+
+    // used to match external template files to precompile
+    var templatePattern = options.reduce(function(result, value) {
+      var match = value.match(/template=(.+)$/);
+      return match
+        ? path.join(fs.realpathSync(path.dirname(match[1])), path.basename(match[1]))
+        : result;
+    }, '');
+
+    // used when precompiling template files
+    var templateSettings = options.reduce(function(result, value) {
+      var match = value.match(/settings=(.+)$/);
+      return match
+        ? _.assign(result, Function('return {' + match[1].replace(/^{|}$/g, '') + '}')())
+        : result;
+    }, _.assign(_.clone(_.templateSettings), {
+      'moduleId': moduleId
+    }));
+
+    // flag to specify a template build
+    var isTemplate = !!templatePattern;
+
+    // the lodash.js source
+    var source = fs.readFileSync(filePath, 'utf8');
+
+    // flag to specify replacing Lo-Dash's `_.clone` with Underscore's
+    var useUnderscoreClone = isUnderscore;
+
+    // flags to specify exposing Lo-Dash methods in an Underscore build
+    var exposeAssign = !isUnderscore,
+        exposeForIn = !isUnderscore,
+        exposeForOwn = !isUnderscore,
+        exposeIsPlainObject = !isUnderscore;
+
+    // flags to specify export options
+    var isAMD = exportsOptions.indexOf('amd') > -1,
+        isCommonJS = exportsOptions.indexOf('commonjs') > -1,
+        isGlobal = exportsOptions.indexOf('global') > -1,
+        isNode = exportsOptions.indexOf('node') > -1;
+
+    /*------------------------------------------------------------------------*/
+
+    // names of methods to include in the build
+    var buildMethods = !isTemplate && (function() {
+      var result;
+
+      var includeMethods = options.reduce(function(accumulator, value) {
+        return /include/.test(value)
+          ? _.union(accumulator, optionToMethodsArray(source, value))
+          : accumulator;
+      }, []);
+
+      var minusMethods = options.reduce(function(accumulator, value) {
+        return /exclude|minus/.test(value)
+          ? _.union(accumulator, optionToMethodsArray(source, value))
+          : accumulator;
+      }, []);
+
+      var plusMethods = options.reduce(function(accumulator, value) {
+        return /plus/.test(value)
+          ? _.union(accumulator, optionToMethodsArray(source, value))
+          : accumulator;
+      }, []);
+
+      // set flags to include Lo-Dash's methods if explicitly requested
+      if (isUnderscore) {
+        var methods = _.without.apply(_, [_.union(includeMethods, plusMethods)].concat(minusMethods));
+        exposeAssign = methods.indexOf('assign') > -1;
+        exposeForIn = methods.indexOf('forIn') > -1;
+        exposeForOwn = methods.indexOf('forOwn') > -1;
+        exposeIsPlainObject = methods.indexOf('isPlainObject') > -1;
+
+        methods = _.without.apply(_, [plusMethods].concat(minusMethods));
+        useUnderscoreClone = methods.indexOf('clone') < 0;
+      }
+      // update dependencies
+      if (isLegacy) {
+        dependencyMap.defer = _.without(dependencyMap.defer, 'bind');
+      }
+      if (isUnderscore) {
+        dependencyMap.contains = _.without(dependencyMap.contains, 'isString');
+        dependencyMap.countBy = _.without(dependencyMap.countBy, 'isEqual', 'keys');
+        dependencyMap.every = _.without(dependencyMap.every, 'isEqual', 'keys');
+        dependencyMap.filter = _.without(dependencyMap.filter, 'isEqual');
+        dependencyMap.find = _.without(dependencyMap.find, 'isEqual', 'keys');
+        dependencyMap.groupBy = _.without(dependencyMap.groupBy, 'isEqual', 'keys');
+        dependencyMap.isEqual = _.without(dependencyMap.isEqual, 'forIn', 'isArguments');
+        dependencyMap.isEmpty = ['isArray', 'isString'];
+        dependencyMap.map = _.without(dependencyMap.map, 'isEqual', 'keys');
+        dependencyMap.max = _.without(dependencyMap.max, 'isEqual', 'isString', 'keys');
+        dependencyMap.min = _.without(dependencyMap.min, 'isEqual', 'isString', 'keys');
+        dependencyMap.pick = _.without(dependencyMap.pick, 'forIn', 'isObject');
+        dependencyMap.reduce = _.without(dependencyMap.reduce, 'isEqual', 'keys');
+        dependencyMap.reject = _.without(dependencyMap.reject, 'isEqual', 'keys');
+        dependencyMap.some = _.without(dependencyMap.some, 'isEqual', 'keys');
+        dependencyMap.sortBy = _.without(dependencyMap.sortBy, 'isEqual', 'keys');
+        dependencyMap.sortedIndex = _.without(dependencyMap.sortedIndex, 'isEqual', 'keys');
+        dependencyMap.template = _.without(dependencyMap.template, 'keys', 'values');
+        dependencyMap.uniq = _.without(dependencyMap.uniq, 'isEqual', 'keys');
+        dependencyMap.where.push('find', 'isEmpty');
+
+        if (useUnderscoreClone) {
+          dependencyMap.clone = _.without(dependencyMap.clone, 'forEach', 'forOwn');
+        }
+      }
+      if (isModern || isUnderscore) {
+        dependencyMap.reduceRight = _.without(dependencyMap.reduceRight, 'isEqual', 'isString');
+      }
+
+      // add method names explicitly
+      if (includeMethods.length) {
+        result = getDependencies(includeMethods);
+      }
+      // add method names required by Backbone and Underscore builds
+      if (isBackbone && !result) {
+        result = getDependencies(backboneDependencies);
+      }
+      else if (isUnderscore && !result) {
+        result = getDependencies(underscoreMethods);
+      }
+      // add method names by category
+      if (categories.length) {
+        result = _.union(result || [], getDependencies(categories.reduce(function(accumulator, category) {
+          // resolve method names belonging to each category (case-insensitive)
+          return accumulator.concat(getMethodsByCategory(source, capitalize(category)));
+        }, [])));
+      }
+      if (!result) {
+        result = allMethods.slice();
+      }
+      if (plusMethods.length) {
+        result = _.union(result, getDependencies(plusMethods));
+      }
+      if (minusMethods.length) {
+        result = _.without.apply(_, [result].concat(minusMethods, getDependants(minusMethods)));
+      }
+      return result;
+    }());
+
+    /*------------------------------------------------------------------------*/
+
+    // load customized Lo-Dash module
+    var lodash = !isTemplate && (function() {
+      var context = vm.createContext({
+        'clearTimeout': clearTimeout,
+        'console': console,
+        'setTimeout': setTimeout
+      });
+
+      source = setUseStrictOption(source, isStrict);
+
+      if (isLegacy) {
+        _.each(['getPrototypeOf', 'isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'], function(varName) {
+          source = replaceVar(source, varName, 'false');
+        });
+
+        source = replaceVar(source, 'noArgsClass', 'true');
+        source = removeKeysOptimization(source);
+      }
+      if (isMobile || isUnderscore) {
+        source = removeKeysOptimization(source);
+      }
+      if (isModern || isUnderscore) {
+        source = removeHasDontEnumBug(source);
+        source = removeHasEnumPrototype(source);
+        source = removeIteratesOwnLast(source);
+        source = removeNoCharByIndex(source);
+        source = removeNoNodeClass(source);
+
+        if (!isMobile) {
+          source = removeNonEnumArgs(source);
+        }
+      }
+      if (isModern) {
+        // remove `_.isPlainObject` fallback
+        source = source.replace(matchFunction(source, 'isPlainObject'), function(match) {
+          return match.replace(/!getPrototypeOf.+?: */, '');
+        });
+      }
+      if (isUnderscore) {
+        // replace `_.assign`
+        source = replaceFunction(source, 'assign', [
+          '  function assign(object) {',
+          '    if (!object) {',
+          '      return object;',
+          '    }',
+          '    for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {',
+          '      var iterable = arguments[argsIndex];',
+          '      if (iterable) {',
+          '        for (var key in iterable) {',
+          '          object[key] = iterable[key];',
+          '        }',
+          '      }',
+          '    }',
+          '    return object;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.clone`
+        if (useUnderscoreClone) {
+          source = replaceFunction(source, 'clone', [
+            '  function clone(value) {',
+            '    return isObject(value)',
+            '      ? (isArray(value) ? slice(value) : assign({}, value))',
+            '      : value',
+            '  }'
+          ].join('\n'));
+        }
+
+        // replace `_.contains`
+        source = replaceFunction(source, 'contains', [
+          '  function contains(collection, target) {',
+          '    var length = collection ? collection.length : 0,',
+          '        result = false;',
+          "    if (typeof length == 'number') {",
+          '      result = indexOf(collection, target) > -1;',
+          '    } else {',
+          '      each(collection, function(value) {',
+          '        return (result = value === target) && indicatorObject;',
+          '      });',
+          '    }',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.defaults`
+        source = replaceFunction(source, 'defaults', [
+          '  function defaults(object) {',
+          '    if (!object) {',
+          '      return object;',
+          '    }',
+          '    for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {',
+          '      var iterable = arguments[argsIndex];',
+          '      if (iterable) {',
+          '        for (var key in iterable) {',
+          '          if (object[key] == null) {',
+          '            object[key] = iterable[key];',
+          '          }',
+          '        }',
+          '      }',
+          '    }',
+          '    return object;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.difference`
+        source = replaceFunction(source, 'difference', [
+          '  function difference(array) {',
+          '    var index = -1,',
+          '        length = array.length,',
+          '        flattened = concat.apply(arrayRef, arguments),',
+          '        result = [];',
+          '',
+          '    while (++index < length) {',
+          '      var value = array[index]',
+          '      if (indexOf(flattened, value, length) < 0) {',
+          '        result.push(value);',
+          '      }',
+          '    }',
+          '    return result',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.intersection`
+        source = replaceFunction(source, 'intersection', [
+          '  function intersection(array) {',
+          '    var args = arguments,',
+          '        argsLength = args.length,',
+          '        index = -1,',
+          '        length = array ? array.length : 0,',
+          '        result = [];',
+          '',
+          '    outer:',
+          '    while (++index < length) {',
+          '      var value = array[index];',
+          '      if (indexOf(result, value) < 0) {',
+          '        var argsIndex = argsLength;',
+          '        while (--argsIndex) {',
+          '          if (indexOf(args[argsIndex], value) < 0) {',
+          '            continue outer;',
+          '          }',
+          '        }',
+          '        result.push(value);',
+          '      }',
+          '    }',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.isEmpty`
+        source = replaceFunction(source, 'isEmpty', [
+          '  function isEmpty(value) {',
+          '    if (!value) {',
+          '      return true;',
+          '    }',
+          '    if (isArray(value) || isString(value)) {',
+          '      return !value.length;',
+          '    }',
+          '    for (var key in value) {',
+          '      if (hasOwnProperty.call(value, key)) {',
+          '        return false;',
+          '      }',
+          '    }',
+          '    return true;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.isEqual`
+        source = replaceFunction(source, 'isEqual', [
+          '  function isEqual(a, b, stackA, stackB) {',
+          '    if (a === b) {',
+          '      return a !== 0 || (1 / a == 1 / b);',
+          '    }',
+          '    var type = typeof a,',
+          '        otherType = typeof b;',
+          '',
+          '    if (a === a &&',
+          "        (!a || (type != 'function' && type != 'object')) &&",
+          "        (!b || (otherType != 'function' && otherType != 'object'))) {",
+          '      return false;',
+          '    }',
+          '    if (a == null || b == null) {',
+          '      return a === b;',
+          '    }',
+          '    var className = toString.call(a),',
+          '        otherClass = toString.call(b);',
+          '',
+          '    if (className != otherClass) {',
+          '      return false;',
+          '    }',
+          '    switch (className) {',
+          '      case boolClass:',
+          '      case dateClass:',
+          '        return +a == +b;',
+          '',
+          '      case numberClass:',
+          '        return a != +a',
+          '          ? b != +b',
+          '          : (a == 0 ? (1 / a == 1 / b) : a == +b);',
+          '',
+          '      case regexpClass:',
+          '      case stringClass:',
+          "        return a == b + '';",
+          '    }',
+          '    var isArr = className == arrayClass;',
+          '    if (!isArr) {',
+          '      if (a.__wrapped__ || b.__wrapped__) {',
+          '        return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, stackA, stackB);',
+          '      }',
+          '      if (className != objectClass) {',
+          '        return false;',
+          '      }',
+          '      var ctorA = a.constructor,',
+          '          ctorB = b.constructor;',
+          '',
+          '      if (ctorA != ctorB && !(',
+          '            isFunction(ctorA) && ctorA instanceof ctorA &&',
+          '            isFunction(ctorB) && ctorB instanceof ctorB',
+          '          )) {',
+          '        return false;',
+          '      }',
+          '    }',
+          '    stackA || (stackA = []);',
+          '    stackB || (stackB = []);',
+          '',
+          '    var length = stackA.length;',
+          '    while (length--) {',
+          '      if (stackA[length] == a) {',
+          '        return stackB[length] == b;',
+          '      }',
+          '    }',
+          '    var result = true,',
+          '        size = 0;',
+          '',
+          '    stackA.push(a);',
+          '    stackB.push(b);',
+          '',
+          '    if (isArr) {',
+          '      size = b.length;',
+          '      result = size == a.length;',
+          '',
+          '      if (result) {',
+          '        while (size--) {',
+          '          if (!(result = isEqual(a[size], b[size], stackA, stackB))) {',
+          '            break;',
+          '          }',
+          '        }',
+          '      }',
+          '      return result;',
+          '    }',
+          '    forIn(b, function(value, key, b) {',
+          '      if (hasOwnProperty.call(b, key)) {',
+          '        size++;',
+          '        return !(result = hasOwnProperty.call(a, key) && isEqual(a[key], value, stackA, stackB)) && indicatorObject;',
+          '      }',
+          '    });',
+          '',
+          '    if (result) {',
+          '      forIn(a, function(value, key, a) {',
+          '        if (hasOwnProperty.call(a, key)) {',
+          '          return !(result = --size > -1) && indicatorObject;',
+          '        }',
+          '      });',
+          '    }',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.omit`
+        source = replaceFunction(source, 'omit', [
+          '  function omit(object) {',
+          '    var props = concat.apply(arrayRef, arguments),',
+          '        result = {};',
+          '',
+          '    forIn(object, function(value, key) {',
+          '      if (indexOf(props, key, 1) < 0) {',
+          '        result[key] = value;',
+          '      }',
+          '    });',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.pick`
+        source = replaceFunction(source, 'pick', [
+          '  function pick(object) {',
+          '    var index = 0,',
+          '        props = concat.apply(arrayRef, arguments),',
+          '        length = props.length,',
+          '        result = {};',
+          '',
+          '    while (++index < length) {',
+          '      var prop = props[index];',
+          '      if (prop in object) {',
+          '        result[prop] = object[prop];',
+          '      }',
+          '    }',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.result`
+        source = replaceFunction(source, 'result', [
+          '  function result(object, property) {',
+          '    var value = object ? object[property] : null;',
+          '    return isFunction(value) ? object[property]() : value;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.template`
+        source = replaceFunction(source, 'template', [
+          '  function template(text, data, options) {',
+          "    text || (text = '');",
+          '    options = defaults({}, options, lodash.templateSettings);',
+          '',
+          '    var index = 0,',
+          '        source = "__p += \'",',
+          '        variable = options.variable;',
+          '',
+          '    var reDelimiters = RegExp(',
+          "      (options.escape || reNoMatch).source + '|' +",
+          "      (options.interpolate || reNoMatch).source + '|' +",
+          "      (options.evaluate || reNoMatch).source + '|$'",
+          "    , 'g');",
+          '',
+          '    text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {',
+          '      source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);',
+          '      if (escapeValue) {',
+          '        source += "\' +\\n_.escape(" + escapeValue + ") +\\n\'";',
+          '      }',
+          '      if (evaluateValue) {',
+          '        source += "\';\\n" + evaluateValue + ";\\n__p += \'";',
+          '      }',
+          '      if (interpolateValue) {',
+          '        source += "\' +\\n((__t = (" + interpolateValue + ")) == null ? \'\' : __t) +\\n\'";',
+          '      }',
+          '      index = offset + match.length;',
+          '      return match;',
+          '    });',
+          '',
+          '    source += "\';\\n";',
+          '    if (!variable) {',
+          "      variable = 'obj';",
+          "      source = 'with (' + variable + ' || {}) {\\n' + source + '\\n}\\n';",
+          '    }',
+          "    source = 'function(' + variable + ') {\\n' +",
+          '      "var __t, __p = \'\', __j = Array.prototype.join;\\n" +',
+          '      "function print() { __p += __j.call(arguments, \'\') }\\n" +',
+          '      source +',
+          "      'return __p\\n}';",
+          '',
+          '    try {',
+          "      var result = Function('_', 'return ' + source)(lodash);",
+          '    } catch(e) {',
+          '      e.source = source;',
+          '      throw e;',
+          '    }',
+          '    if (data) {',
+          '      return result(data);',
+          '    }',
+          '    result.source = source;',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.uniq`
+        source = replaceFunction(source, 'uniq', [
+          '  function uniq(array, isSorted, callback, thisArg) {',
+          '    var index = -1,',
+          '        length = array ? array.length : 0,',
+          '        result = [],',
+          '        seen = result;',
+          '',
+          "    if (typeof isSorted == 'function') {",
+          '      thisArg = callback;',
+          '      callback = isSorted;',
+          '      isSorted = false;',
+          '    }',
+          '    if (callback) {',
+          '      seen = [];',
+          '      callback = createCallback(callback, thisArg);',
+          '    }',
+          '    while (++index < length) {',
+          '      var value = array[index],',
+          '          computed = callback ? callback(value, index, array) : value;',
+          '',
+          '      if (isSorted',
+          '            ? !index || seen[seen.length - 1] !== computed',
+          '            : indexOf(seen, computed) < 0',
+          '          ) {',
+          '        if (callback) {',
+          '          seen.push(computed);',
+          '        }',
+          '        result.push(value);',
+          '      }',
+          '    }',
+          '    return result;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.uniqueId`
+        source = replaceFunction(source, 'uniqueId', [
+          '  function uniqueId(prefix) {',
+          "    var id = ++idCounter + '';",
+          '    return prefix ? prefix + id : id;',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.where`
+        source = replaceFunction(source, 'where', [
+          '  function where(collection, properties, first) {',
+          '    return (first && isEmpty(properties))',
+          '      ? null',
+          '      : (first ? find : filter)(collection, properties);',
+          '  }'
+        ].join('\n'));
+
+        // replace `_.without`
+        source = replaceFunction(source, 'without', [
+          '  function without(array) {',
+          '    var index = -1,',
+          '        length = array.length,',
+          '        result = [];',
+          '',
+          '    while (++index < length) {',
+          '      var value = array[index]',
+          '      if (indexOf(arguments, value, 1) < 0) {',
+          '        result.push(value);',
+          '      }',
+          '    }',
+          '    return result',
+          '  }'
+        ].join('\n'));
+
+        // add `_.findWhere`
+        source = source.replace(matchFunction(source, 'find'), function (match) {
+          return match + [
+            '',
+            '  function findWhere(object, properties) {',
+            '    return where(object, properties, true);',
+            '  }',
+            ''
+          ].join('\n')
+        });
+
+        source = source.replace(getMethodAssignments(source), function(match) {
+          return match.replace(/^( *)lodash.find *=.+/m, '$&\n$1lodash.findWhere = findWhere;');
+        });
+
+        // add Underscore style chaining
+        source = addChainMethods(source);
+
+        // remove `_.templateSettings.imports assignment
+        source = source.replace(/,[^']*'imports':[^}]+}/, '');
+
+        // remove large array optimizations
+        source = removeFunction(source, 'cachedContains');
+        source = removeVar(source, 'largeArraySize');
+
+        // remove `_.isEqual` use from `createCallback`
+        source = source.replace(matchFunction(source, 'createCallback'), function(match) {
+          return match.replace(/isEqual\(([^,]+), *([^,]+)[^)]+\)/, '$1 === $2');
+        });
+
+        // remove conditional `charCodeCallback` use from `_.max` and `_.min`
+        _.each(['max', 'min'], function(methodName) {
+          source = source.replace(matchFunction(source, methodName), function(match) {
+            return match.replace(/!callback *&& *isString\(collection\)[\s\S]+?: */g, '');
+          });
+        });
+
+        // remove unneeded variables
+        if (useUnderscoreClone) {
+          source = removeVar(source, 'cloneableClasses');
+          source = removeVar(source, 'ctorByClass');
+        }
+        // remove unused features from `createBound`
+        if (buildMethods.indexOf('partial') < 0 && buildMethods.indexOf('partialRight') < 0) {
+          source = source.replace(matchFunction(source, 'createBound'), function(match) {
+            return match
+              .replace(/, *right[^)]*/, '')
+              .replace(/(function createBound\([^{]+{)[\s\S]+?(\n *function bound)/, '$1$2')
+              .replace(/thisBinding *=[^}]+}/, 'thisBinding = thisArg;\n')
+              .replace(/\(args *=.+/, 'partialArgs.concat(slice(args))');
+          });
+        }
+      }
+      vm.runInContext(source, context);
+      return context._;
+    }());
+
+    /*------------------------------------------------------------------------*/
+
+    if (isTemplate) {
+      source = buildTemplate(templatePattern, templateSettings);
+    }
+    else {
+      // remove methods from the build
+      allMethods.forEach(function(otherName) {
+        if (!_.contains(buildMethods, otherName)) {
+          source = removeFunction(source, otherName);
+        }
+      });
+
+      // remove `isArguments` fallback before `isArguments` is transformed by
+      // other parts of the build process
+      if (isRemoved(source, 'isArguments')) {
+        source = removeIsArgumentsFallback(source);
+      }
+
+      // remove `iteratorTemplate` dependency checks from `_.template`
+      source = source.replace(matchFunction(source, 'template'), function(match) {
+        return match
+          .replace(/iteratorTemplate *&& */g, '')
+          .replace(/iteratorTemplate *\? *([^:]+?) *:[^,;]+/g, '$1');
+      });
+
+      /*----------------------------------------------------------------------*/
+
+      if (isLegacy) {
+        source = removeSetImmediate(source);
+
+        _.each(['isBindFast', 'isV8', 'nativeBind', 'nativeIsArray', 'nativeKeys', 'reNative'], function(varName) {
+          source = removeVar(source, varName);
+        });
+
+        // remove native `Function#bind` branch in `_.bind`
+        source = source.replace(matchFunction(source, 'bind'), function(match) {
+          return match.replace(/(?:\s*\/\/.*)*\s*return isBindFast[^:]+:\s*/, 'return ');
+        });
+
+        // remove native `Array.isArray` branch in `_.isArray`
+        source = source.replace(matchFunction(source, 'isArray'), function(match) {
+          return match.replace(/nativeIsArray * \|\|\s*/, '');
+        });
+
+        // replace `_.keys` with `shimKeys`
+        if (!isRemoved(source, 'keys')) {
+          source = source.replace(
+            matchFunction(source, 'keys').replace(/[\s\S]+?var keys *= */, ''),
+            matchFunction(source, 'shimKeys').replace(/[\s\S]+?function shimKeys/, 'function').replace(/}\n$/, '};\n')
+          );
+
+          source = removeFunction(source, 'shimKeys');
+        }
+        // replace `_.isArguments` with fallback
+        if (!isRemoved(source, 'isArguments')) {
+          source = source.replace(
+            matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''),
+            getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + '  }\n'
+          );
+
+          source = removeIsArgumentsFallback(source);
+        }
+      }
+      if (isModern) {
+        source = removeArgsAreObjects(source);
+        source = removeHasObjectSpliceBug(source);
+        source = removeIsArgumentsFallback(source);
+      }
+      if (isModern || isUnderscore) {
+        source = removeNoArgsClass(source);
+        source = removeNoNodeClass(source);
+      }
+      if (isMobile || isUnderscore) {
+        source = removeVar(source, 'iteratorTemplate');
+
+        // inline all functions defined with `createIterator`
+        _.functions(lodash).forEach(function(methodName) {
+          // strip leading underscores to match pseudo private functions
+          var reFunc = RegExp('(\\bvar ' + methodName.replace(/^_/, '') + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n');
+          if (reFunc.test(source)) {
+            // extract, format, and inject the compiled function's source code
+            source = source.replace(reFunc, function(match, captured) {
+              return captured + getFunctionSource(lodash[methodName]) + ';\n';
+            });
+          }
+        });
+      }
+      if (isUnderscore) {
+        // remove `_.assign`, `_.forIn`, `_.forOwn`, and `_.isPlainObject` assignments
+        (function() {
+          var snippet = getMethodAssignments(source),
+              modified = snippet;
+
+          if (!exposeAssign) {
+            modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.assign *= *.+\n/m, '');
+          }
+          if (!exposeForIn) {
+            modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.forIn *= *.+\n/m, '');
+          }
+          if (!exposeForOwn) {
+            modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.forOwn *= *.+\n/m, '');
+          }
+          if (!exposeIsPlainObject) {
+            modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.isPlainObject *= *.+\n/m, '');
+          }
+          source = source.replace(snippet, modified);
+        }());
+
+        // remove `thisArg` from unexposed `forIn` and `forOwn`
+        _.each([
+          { 'methodName': 'forIn', 'flag': exposeForIn },
+          { 'methodName': 'forOwn', 'flag': exposeForOwn }
+        ], function(data) {
+          if (!data.flag) {
+            source = source.replace(matchFunction(source, data.methodName), function(match) {
+              return match
+                .replace(/(callback), *thisArg/g, '$1')
+                .replace(/^( *)callback *=.+/m, '$1callback || (callback = identity);')
+            });
+          }
+        });
+
+        // remove chainability from `each` and `_.forEach`
+        _.each(['each', 'forEach'], function(methodName) {
+          source = source.replace(matchFunction(source, methodName), function(match) {
+            return match.replace(/\n *return .+?([};\s]+)$/, '$1');
+          });
+        });
+
+        // unexpose "exit early" feature of `each`, `_.forEach`, `_.forIn`, and `_.forOwn`
+        _.each(['each', 'forEach', 'forIn', 'forOwn'], function(methodName) {
+          source = source.replace(matchFunction(source, methodName), function(match) {
+            return match.replace(/=== *false\)/g, '=== indicatorObject)');
+          });
+        });
+
+        // modify `_.every`, `_.find`, `_.isEqual`, and `_.some` to use the private `indicatorObject`
+        _.each(['every', 'isEqual'], function(methodName) {
+          source = source.replace(matchFunction(source, methodName), function(match) {
+            return match.replace(/\(result *= *(.+?)\);/g, '!(result = $1) && indicatorObject;');
+          });
+        });
+
+        source = source.replace(matchFunction(source, 'find'), function(match) {
+          return match.replace(/return false/, 'return indicatorObject');
+        });
+
+        source = source.replace(matchFunction(source, 'some'), function(match) {
+          return match.replace(/!\(result *= *(.+?)\);/, '(result = $1) && indicatorObject;');
+        });
+      }
+      if (!(isMobile || isUnderscore)) {
+        // inline `iteratorTemplate` template
+        source = source.replace(getIteratorTemplate(source), function() {
+          var snippet = getFunctionSource(lodash._iteratorTemplate);
+
+          // prepend data object references to property names to avoid having to
+          // use a with-statement
+          iteratorOptions.forEach(function(property) {
+            snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
+          });
+
+          // remove unnecessary code
+          snippet = snippet
+            .replace(/var __t.+/, "var __p = '';")
+            .replace(/function print[^}]+}/, '')
+            .replace(/'(?:\\n|\s)+'/g, "''")
+            .replace(/__p *\+= *' *';/g, '')
+            .replace(/(__p *\+= *)' *' *\+/g, '$1')
+            .replace(/({) *;|; *(})/g, '$1$2')
+            .replace(/\(\(__t *= *\( *([^)]+) *\)\) *== *null *\? *'' *: *__t\)/g, '($1)');
+
+          // remove the with-statement
+          snippet = snippet.replace(/ *with *\(.+?\) *{/, '\n').replace(/}([^}]*}[^}]*$)/, '$1');
+
+          // minor cleanup
+          snippet = snippet
+            .replace(/obj *\|\|\s*\(obj *= *{}\);/, '')
+            .replace(/var __p = '';\s*__p \+=/, 'var __p =');
+
+          // remove comments, including sourceURLs
+          snippet = snippet.replace(/\s*\/\/.*(?:\n|$)/g, '');
+
+          return '  var iteratorTemplate = ' + snippet + ';\n';
+        });
+      }
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    // customize Lo-Dash's IIFE
+    (function() {
+      if (isIIFE) {
+        var token = '%output%',
+            index = iife.indexOf(token);
+
+        source = source.match(/^\/\**[\s\S]+?\*\/\n/) +
+          iife.slice(0, index) +
+          source.replace(/^[\s\S]+?\(function[^{]+?{|}\(this\)\)[;\s]*$/g, '') +
+          iife.slice(index + token.length);
+      }
+    }());
+
+    /*------------------------------------------------------------------------*/
+
+    // customize Lo-Dash's export bootstrap
+    (function() {
+      if (!isAMD) {
+        source = source.replace(/(?: *\/\/.*\n)*( *)if *\(typeof +define[\s\S]+?else /, '$1');
+      }
+      if (!isNode) {
+        source = source.replace(/(?: *\/\/.*\n)*( *)if *\(freeModule[\s\S]+?else *{([\s\S]+?\n)\1}\n/, '$1$2');
+      }
+      if (!isCommonJS) {
+        source = source.replace(/(?: *\/\/.*\n)*(?:( *)else *{)?\s*freeExports\.\w+ *=[\s\S]+?(?:\n\1})?\n/, '');
+      }
+      if (!isGlobal) {
+        source = source.replace(/(?:( *)(})? *else(?: *if *\(_\))? *{)?(?:\s*\/\/.*)*\s*(?:window\._|_\.templates) *=[\s\S]+?(?:\n\1})?\n/g, '$1$2\n');
+      }
+      // remove `if (freeExports) {...}` if it's empty
+      if (isAMD && isGlobal) {
+        source = source.replace(/(?: *\/\/.*\n)* *(?:else )?if *\(freeExports\) *{\s*}\n/, '');
+      } else {
+        source = source.replace(/(?: *\/\/.*\n)* *(?:else )?if *\(freeExports\) *{\s*}(?:\s*else *{([\s\S]+?) *})?\n/, '$1\n');
+      }
+    }());
+
+    /*------------------------------------------------------------------------*/
+
+    if (!isTemplate) {
+      // modify/remove references to removed methods/variables
+      if (isRemoved(source, 'invert')) {
+        source = replaceVar(source, 'htmlUnescapes', "{'&amp;':'&','&lt;':'<','&gt;':'>','&quot;':'\"','&#x27;':\"'\"}");
+      }
+      if (isRemoved(source, 'isArguments')) {
+        source = replaceVar(source, 'noArgsClass', 'false');
+      }
+      if (isRemoved(source, 'isFunction')) {
+        source = removeIsFunctionFallback(source);
+      }
+      if (isRemoved(source, 'mixin')) {
+        source = removeHasObjectSpliceBug(source);
+
+        // simplify the `lodash` function
+        source = replaceFunction(source, 'lodash', [
+          '  function lodash() {',
+          '    // no operation performed',
+          '  }'
+        ].join('\n'));
+
+        // remove all `lodash.prototype` additions
+        source = source
+          .replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, '')
+          .replace(/(?:\s*\/\/.*)*\n( *)each\(\['[\s\S]+?\n\1}.+/g, '')
+          .replace(/(?:\s*\/\/.*)*\s*lodash\.prototype.+\n/g, '')
+          .replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+\n/, '');
+      }
+      // remove functions, variables, and snippets that the minifier may miss
+      if (isRemoved(source, 'clone')) {
+        source = removeVar(source, 'cloneableClasses');
+        source = removeVar(source, 'ctorByClass');
+      }
+      if (isRemoved(source, 'isArray')) {
+        source = removeVar(source, 'nativeIsArray');
+      }
+      if (isRemoved(source, 'isPlainObject')) {
+        source = removeVar(source, 'getPrototypeOf');
+        source = removeIteratesOwnLast(source);
+      }
+      if (isRemoved(source, 'keys')) {
+        source = removeFunction(source, 'shimKeys');
+      }
+      if (isRemoved(source, 'template')) {
+        // remove `templateSettings` assignment
+        source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
+      }
+      if (isRemoved(source, 'isArguments', 'isEmpty')) {
+        source = removeNoArgsClass(source);
+      }
+      if (isRemoved(source, 'clone', 'isEqual', 'isPlainObject')) {
+        source = removeNoNodeClass(source);
+      }
+      if ((source.match(/\bcreateIterator\b/g) || []).length < 2) {
+        source = removeFunction(source, 'createIterator');
+        source = removeVar(source, 'defaultsIteratorOptions');
+        source = removeVar(source, 'eachIteratorOptions');
+        source = removeVar(source, 'forOwnIteratorOptions');
+        source = removeVar(source, 'templateIterator');
+        source = removeHasDontEnumBug(source);
+        source = removeHasEnumPrototype(source);
+      }
+      if (isRemoved(source, 'createIterator', 'bind', 'keys')) {
+        source = removeSetImmediate(source);
+        source = removeVar(source, 'isBindFast');
+        source = removeVar(source, 'isV8');
+        source = removeVar(source, 'nativeBind');
+      }
+      if (isRemoved(source, 'createIterator', 'keys')) {
+        source = removeVar(source, 'nativeKeys');
+        source = removeKeysOptimization(source);
+        source = removeNonEnumArgs(source);
+      }
+      if (!source.match(/var (?:hasDontEnumBug|hasEnumPrototype|iteratesOwnLast|nonEnumArgs)\b/g)) {
+        // remove IIFE used to assign `hasDontEnumBug`, `hasEnumPrototype`, `iteratesOwnLast`, and `nonEnumArgs`
+        source = source.replace(/^ *\(function\(\) *{[\s\S]+?}\(1\)\);\n/m, '');
+      }
+    }
+    if ((source.match(/\bfreeModule\b/g) || []).length < 2) {
+      source = removeVar(source, 'freeModule');
+    }
+    if ((source.match(/\bfreeExports\b/g) || []).length < 2) {
+      source = removeVar(source, 'freeExports');
+    }
+
+    debugSource = cleanupSource(source);
+    source = cleanupSource(source);
+
+    /*------------------------------------------------------------------------*/
+
+    // flag to track if `outputPath` has been used by `callback`
+    var outputUsed = false;
+
+    // flag to specify creating a custom build
+    var isCustom = (
+      isLegacy || isMapped || isModern || isStrict || isUnderscore || outputPath ||
+      /(?:category|exclude|exports|iife|include|minus|plus)=/.test(options) ||
+      !_.isEqual(exportsOptions, exportsAll)
+    );
+
+    // used as the basename of the output path
+    var basename = outputPath
+      ? path.basename(outputPath, '.js')
+      : 'lodash' + (isTemplate ? '.template' : isCustom ? '.custom' : '');
+
+    // restore `dependencyMap`
+    dependencyMap = dependencyBackup;
+
+    // output debug build
+    if (!isMinify && (isCustom || isDebug || isTemplate)) {
+      if (isCustom) {
+        debugSource = addCommandsToHeader(debugSource, options);
+      }
+      if (isDebug && isStdOut) {
+        stdout.write(debugSource);
+        callback({
+          'source': debugSource
+        });
+      }
+      else if (!isStdOut) {
+        filePath = outputPath || path.join(cwd, basename + '.js');
+        outputUsed = true;
+        callback({
+          'source': debugSource,
+          'outputPath': filePath
+        });
+      }
+    }
+    // begin the minification process
+    if (!isDebug) {
+      if (outputPath && outputUsed) {
+        outputPath = path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.min.js');
+      } else if (!outputPath) {
+        outputPath = path.join(cwd, basename + '.min.js');
+      }
+      minify(source, {
+        'filePath': filePath,
+        'isMapped': isMapped,
+        'isSilent': isSilent,
+        'isTemplate': isTemplate,
+        'modes': isIIFE && ['simple', 'hybrid'],
+        'outputPath': outputPath,
+        'sourceMapURL': sourceMapURL,
+        'onComplete': function(data) {
+          if (isCustom) {
+            data.source = addCommandsToHeader(data.source, options);
+          }
+          if (isStdOut) {
+            stdout.write(data.source);
+            callback(data);
+          } else {
+            callback(data);
+          }
+        }
+      });
+    }
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose `build`
+  if (module != require.main) {
+    module.exports = build;
+  }
+  else {
+    // or invoked directly
+    build(process.argv, function(data) {
+      var outputPath = data.outputPath,
+          sourceMap = data.sourceMap;
+
+      if (outputPath) {
+        fs.writeFileSync(outputPath, data.source, 'utf8');
+        if (sourceMap) {
+          fs.writeFileSync(path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map'), sourceMap, 'utf8');
+        }
+      }
+    });
+  }
+}());
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/minify.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/minify.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/minify.js	(revision 533)
@@ -0,0 +1,753 @@
+#!/usr/bin/env node
+;(function() {
+  'use strict';
+
+  /** Load Node modules */
+  var fs = require('fs'),
+      https = require('https'),
+      path = require('path'),
+      spawn = require('child_process').spawn,
+      zlib = require('zlib'),
+      tar = require('../vendor/tar/tar.js'),
+      _ = require('../lodash.js');
+
+  /** Load other modules */
+  var preprocess = require('./pre-compile.js'),
+      postprocess = require('./post-compile.js');
+
+  /** The Git object ID of `closure-compiler.tar.gz` */
+  var closureId = '23cf67d0f0b979d97631fc108a2a43bb82225994';
+
+  /** The Git object ID of `uglifyjs.tar.gz` */
+  var uglifyId = 'a934fb18f8fa2768c6a68de44b6e035fe96a268b';
+
+  /** The path of the directory that is the base of the repository */
+  var basePath = fs.realpathSync(path.join(__dirname, '..'));
+
+  /** The path of the `vendor` directory */
+  var vendorPath = path.join(basePath, 'vendor');
+
+  /** The path to the Closure Compiler `.jar` */
+  var closurePath = path.join(vendorPath, 'closure-compiler', 'compiler.jar');
+
+  /** The path to the UglifyJS module */
+  var uglifyPath = path.join(vendorPath, 'uglifyjs', 'tools', 'node.js');
+
+  /** The Closure Compiler command-line options */
+  var closureOptions = ['--warning_level=QUIET'];
+
+  /** The media type for raw blob data */
+  var mediaType = 'application/vnd.github.v3.raw';
+
+  /** Used to reference parts of the blob href */
+  var location = (function() {
+    var host = 'api.github.com',
+        origin = 'https://api.github.com',
+        pathname = '/repos/bestiejs/lodash/git/blobs';
+
+    return {
+      'host': host,
+      'href': origin + pathname,
+      'origin': origin,
+      'pathname': pathname
+    };
+  }());
+
+  /** The Closure Compiler optimization modes */
+  var optimizationModes = {
+    'simple': 'SIMPLE_OPTIMIZATIONS',
+    'advanced': 'ADVANCED_OPTIMIZATIONS'
+  };
+
+  /** Reassign `existsSync` for older versions of Node */
+  fs.existsSync || (fs.existsSync = path.existsSync);
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Minifies a given Lo-Dash `source` and invokes the `options.onComplete`
+   * callback when finished. The `onComplete` callback is invoked with one
+   * argument; (outputSource).
+   *
+   * @param {Array|String} [source=''] The source to minify or array of commands.
+   *  -o, --output - Write output to a given path/filename.
+   *  -s, --silent - Skip status updates normally logged to the console.
+   *  -t, --template - Applies template specific minifier options.
+   *
+   * @param {Object} [options={}] The options object.
+   *  outputPath - Write output to a given path/filename.
+   *  isSilent - Skip status updates normally logged to the console.
+   *  isTemplate - Applies template specific minifier options.
+   *  onComplete - The function called once minification has finished.
+   */
+  function minify(source, options) {
+    // used to specify the source map URL
+    var sourceMapURL;
+
+    // used to specify the default minifer modes
+    var modes = ['simple', 'advanced', 'hybrid'];
+
+    source || (source = '');
+    options || (options = {});
+
+    // juggle arguments
+    if (Array.isArray(source)) {
+      // convert commands to an options object
+      options = source;
+
+      // used to report invalid command-line arguments
+      var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
+        if (/^(?:-o|--output)$/.test(options[index - 1]) ||
+            /^modes=.*$/.test(value)) {
+          return true;
+        }
+        var result = [
+          '-o', '--output',
+          '-p', '--source-map',
+          '-s', '--silent',
+          '-t', '--template'
+        ].indexOf(value) > -1;
+
+        if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
+          result = true;
+          sourceMapURL = value;
+        }
+        return result;
+      });
+
+      // report invalid arguments
+      if (invalidArgs.length) {
+        console.log(
+          '\n' +
+          'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
+          ' passed: ' + invalidArgs.join(', ')
+        );
+        return;
+      }
+      var filePath = options[options.length - 1],
+          isMapped = options.indexOf('-p') > -1 || options.indexOf('--source-map') > -1,
+          isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1,
+          isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
+          outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
+
+      modes = options.reduce(function(result, value) {
+        var match = value.match(/modes=(.*)$/);
+        return match ? match[1].split(/, */) : result;
+      }, modes);
+
+      outputPath = options.reduce(function(result, value, index) {
+        if (/-o|--output/.test(value)) {
+          result = options[index + 1];
+          result = path.join(fs.realpathSync(path.dirname(result)), path.basename(result));
+        }
+        return result;
+      }, outputPath);
+
+      options = {
+        'filePath': filePath,
+        'isMapped': isMapped,
+        'isSilent': isSilent,
+        'isTemplate': isTemplate,
+        'modes': modes,
+        'outputPath': outputPath,
+        'sourceMapURL': sourceMapURL
+      };
+
+      source = fs.readFileSync(filePath, 'utf8');
+    }
+
+    modes = options.modes || modes;
+    if (options.isMapped) {
+      modes = modes.filter(function(mode) {
+        return mode != 'hybrid';
+      });
+    }
+    if (options.isTemplate) {
+      modes = modes.filter(function(mode) {
+        return mode != 'advanced';
+      });
+    }
+    options.modes = modes;
+
+    // fetch the Closure Compiler
+    getDependency({
+      'id': 'closure-compiler',
+      'hashId': closureId,
+      'path': vendorPath,
+      'title': 'the Closure Compiler',
+      'onComplete': function(exception) {
+        var error = exception;
+
+        // fetch UglifyJS
+        getDependency({
+          'id': 'uglifyjs',
+          'hashId': uglifyId,
+          'title': 'UglifyJS',
+          'path': vendorPath,
+          'onComplete': function(exception) {
+            error || (error = exception);
+            if (!error) {
+              new Minify(source, options);
+            }
+          }
+        });
+      }
+    });
+  }
+
+  /**
+   * The Minify constructor used to keep state of each `minify` invocation.
+   *
+   * @private
+   * @constructor
+   * @param {String} source The source to minify.
+   * @param {Object} options The options object.
+   *  outputPath - Write output to a given path/filename.
+   *  isSilent - Skip status updates normally logged to the console.
+   *  isTemplate - Applies template specific minifier options.
+   *  onComplete - The function called once minification has finished.
+   */
+  function Minify(source, options) {
+    // juggle arguments
+    if (typeof source == 'object' && source) {
+      options = source || options;
+      source = options.source || '';
+    }
+    this.compiled = { 'simple': {}, 'advanced': {} };
+    this.hybrid = { 'simple': {}, 'advanced': {} };
+    this.uglified = {};
+
+    this.filePath = options.filePath;
+    this.isMapped = !!options.isMapped;
+    this.isSilent = !!options.isSilent;
+    this.isTemplate = !!options.isTemplate;
+    this.outputPath = options.outputPath;
+    this.sourceMapURL = options.sourceMapURL;
+
+    var modes = this.modes = options.modes;
+    source = this.source = preprocess(source, options);
+
+    this.onComplete = options.onComplete || function(data) {
+      var outputPath = this.outputPath,
+          sourceMap = data.sourceMap;
+
+      fs.writeFileSync(outputPath, data.source, 'utf8');
+      if (sourceMap) {
+        fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
+      }
+    };
+
+    // begin the minification process
+    if (modes.indexOf('simple') > -1) {
+      closureCompile.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
+    } else if (modes.indexOf('advanced') > -1) {
+      onClosureSimpleGzip.call(this);
+    } else {
+      onClosureAdvancedGzip.call(this);
+    }
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Fetches a required `.tar.gz` dependency with the given Git object ID from
+   * the Lo-Dash repo on GitHub. The object ID may be obtained by running
+   * `git hash-object path/to/dependency.tar.gz`.
+   *
+   * @private
+   * @param {Object} options The options object.
+   *  id - The Git object ID of the `.tar.gz` file.
+   *  onComplete - The function called once the extraction has finished.
+   *  path - The path of the extraction directory.
+   *  title - The dependency's title used in status updates logged to the console.
+   */
+  function getDependency(options) {
+    options || (options = {});
+
+    var ran,
+        destPath = options.path,
+        hashId = options.hashId,
+        id = options.id,
+        onComplete = options.onComplete,
+        title = options.title;
+
+    // exit early if dependency exists
+    if (fs.existsSync(path.join(destPath, id))) {
+      onComplete();
+      return;
+    }
+    var callback = function(exception) {
+      if (ran) {
+        return;
+      }
+      if (exception) {
+        console.error([
+          'There was a problem installing ' + title + '.',
+          'Try running the command as root, via `sudo`, or manually install by running:',
+          '',
+          "curl -H 'Accept: " + mediaType + "' " + location.href + '/' + hashId + " | tar xvz -C '" + destPath + "'",
+          ''
+        ].join('\n'));
+      }
+      ran = true;
+      process.removeListener('uncaughtException', callback);
+      onComplete(exception);
+    };
+
+    console.log('Downloading ' + title + '...');
+    process.on('uncaughtException', callback);
+
+    https.get({
+      'host': location.host,
+      'path': location.pathname + '/' + hashId,
+      'headers': {
+        // By default, all GitHub blob API endpoints return a JSON document
+        // containing Base64-encoded blob data. Overriding the `Accept` header
+        // with the GitHub raw media type returns the blob data directly.
+        // See http://developer.github.com/v3/media/.
+        'Accept': mediaType
+      }
+    }, function(response) {
+      var decompressor = zlib.createUnzip(),
+          parser = new tar.Extract({ 'path': destPath });
+
+      parser.on('end', callback);
+      response.pipe(decompressor).pipe(parser);
+    });
+  }
+
+  /**
+   * Resolves the source map path from the given output path.
+   *
+   * @private
+   * @param {String} outputPath The output path.
+   * @returns {String} Returns the source map path.
+   */
+  function getMapPath(outputPath) {
+    return path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map');
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Compresses a `source` string using the Closure Compiler. Yields the
+   * minified result, and any exceptions encountered, to a `callback` function.
+   *
+   * @private
+   * @param {String} source The JavaScript source to minify.
+   * @param {String} mode The optimization mode.
+   * @param {Function} callback The function called once the process has completed.
+   */
+  function closureCompile(source, mode, callback) {
+    var filePath = this.filePath,
+        isAdvanced = mode == 'advanced',
+        isMapped = this.isMapped,
+        options = closureOptions.slice(),
+        outputPath = this.outputPath,
+        mapPath = getMapPath(outputPath),
+        sourceMapURL = this.sourceMapURL || path.basename(mapPath);
+
+    // remove copyright header to make other modifications easier
+    var license = (/^(?:\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*/.exec(source) || [''])[0];
+    if (license) {
+      source = source.replace(license, '');
+    }
+
+    var hasIIFE = /^;?\(function[^{]+{\s*/.test(source),
+        isStrict = hasIIFE && /^;?\(function[^{]+{\s*["']use strict["']/.test(source);
+
+    // to avoid stripping the IIFE, convert it to a function call
+    if (hasIIFE && isAdvanced) {
+      source = source
+        .replace(/\(function/, '__iife__$&')
+        .replace(/\(this\)\)([\s;]*(\n\/\/.+)?)$/, ', this)$1');
+    }
+
+    options.push('--compilation_level=' + optimizationModes[mode]);
+    if (isMapped) {
+      options.push('--create_source_map=' + mapPath, '--source_map_format=V3');
+    }
+
+    var compiler = spawn('java', ['-jar', closurePath].concat(options));
+    if (!this.isSilent) {
+      console.log('Compressing ' + path.basename(outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
+    }
+
+    var error = '';
+    compiler.stderr.on('data', function(data) {
+      error += data;
+    });
+
+    var output = '';
+    compiler.stdout.on('data', function(data) {
+      output += data;
+    });
+
+    compiler.on('exit', function(status) {
+      // `status` contains the process exit code
+      if (status) {
+        var exception = new Error(error);
+        exception.status = status;
+      }
+      // restore IIFE and move exposed vars inside the IIFE
+      if (hasIIFE && isAdvanced) {
+        output = output
+          .replace(/__iife__\(/, '(')
+          .replace(/,\s*this\)([\s;]*(\n\/\/.+)?)$/, '(this))$1')
+          .replace(/^((?:var (?:\w+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^{]+{)/, '$2$1');
+      }
+      // inject "use strict" directive
+      if (isStrict) {
+        output = output.replace(/^[\s\S]*?function[^{]+{/, '$&"use strict";');
+      }
+      // restore copyright header
+      if (license) {
+        output = license + output;
+      }
+      if (isMapped) {
+        var mapOutput = fs.readFileSync(mapPath, 'utf8');
+        fs.unlinkSync(mapPath);
+        output = output.replace(/[\s;]*$/, '\n/*\n//@ sourceMappingURL=' + sourceMapURL) + '\n*/';
+
+        mapOutput = JSON.parse(mapOutput);
+        mapOutput.file = path.basename(outputPath);
+        mapOutput.sources = [path.basename(filePath)];
+        mapOutput = JSON.stringify(mapOutput, null, 2);
+      }
+      callback(exception, output, mapOutput);
+    });
+
+    // proxy the standard input to the Closure Compiler
+    compiler.stdin.end(source);
+  }
+
+  /**
+   * Compresses a `source` string using UglifyJS. Yields the result to a
+   * `callback` function. This function is synchronous; the `callback` is used
+   * for symmetry.
+   *
+   * @private
+   * @param {String} source The JavaScript source to minify.
+   * @param {String} label The label to log.
+   * @param {Function} callback The function called once the process has completed.
+   */
+  function uglify(source, label, callback) {
+    if (!this.isSilent) {
+      console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using ' + label + '...');
+    }
+    try {
+      var uglifyJS = require(uglifyPath);
+
+      // 1. parse
+      var toplevel = uglifyJS.parse(source);
+
+      // 2. compress
+      // enable unsafe comparisons
+      toplevel.figure_out_scope();
+      toplevel = toplevel.transform(uglifyJS.Compressor({
+        'comparisons': false,
+        'unsafe_comps': true,
+        'warnings': false
+      }));
+
+      // 3. mangle
+      // excluding the `define` function exposed by AMD loaders
+      toplevel.figure_out_scope();
+      toplevel.compute_char_frequency();
+      toplevel.mangle_names({
+        'except': ['define']
+      });
+
+      // 4. output
+      // restrict lines to 500 characters for consistency with the Closure Compiler
+      var stream = uglifyJS.OutputStream({
+        'ascii_only': true,
+        'comments': /@cc_on|@license|@preserve/i,
+        'max_line_len': 500,
+      });
+
+      toplevel.print(stream);
+    }
+    catch(e) {
+      var exception = e;
+    }
+    callback(exception, stream && String(stream));
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The Closure Compiler callback for simple optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {String} result The resulting minified source.
+   * @param {String} map The source map output.
+   */
+  function onClosureSimpleCompile(exception, result, map) {
+    if (exception) {
+      throw exception;
+    }
+    result = postprocess(result);
+
+    var simple = this.compiled.simple;
+    simple.source = result;
+    simple.sourceMap = map;
+    zlib.gzip(result, onClosureSimpleGzip.bind(this));
+  }
+
+  /**
+   * The Closure Compiler `gzip` callback for simple optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {Buffer} result The resulting gzipped source.
+   */
+  function onClosureSimpleGzip(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    if (result != null) {
+      if (!this.isSilent) {
+        console.log('Done. Size: %d bytes.', result.length);
+      }
+      this.compiled.simple.gzip = result;
+    }
+    // compile the source using advanced optimizations
+    if (this.modes.indexOf('advanced') > -1) {
+      closureCompile.call(this, this.source, 'advanced', onClosureAdvancedCompile.bind(this));
+    } else {
+      onClosureAdvancedGzip.call(this);
+    }
+  }
+
+  /**
+   * The Closure Compiler callback for advanced optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {String} result The resulting minified source.
+   * @param {String} map The source map output.
+   */
+  function onClosureAdvancedCompile(exception, result, map) {
+    if (exception) {
+      throw exception;
+    }
+    result = postprocess(result);
+
+    var advanced = this.compiled.advanced;
+    advanced.source = result;
+    advanced.sourceMap = map;
+    zlib.gzip(result, onClosureAdvancedGzip.bind(this));
+  }
+
+  /**
+   * The Closure Compiler `gzip` callback for advanced optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {Buffer} result The resulting gzipped source.
+   */
+  function onClosureAdvancedGzip(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    if (result != null) {
+      if (!this.isSilent) {
+        console.log('Done. Size: %d bytes.', result.length);
+      }
+      this.compiled.advanced.gzip = result;
+    }
+    // minify the source using UglifyJS
+    if (!this.isMapped) {
+      uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
+    } else {
+      onComplete.call(this);
+    }
+  }
+
+  /**
+   * The UglifyJS callback.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {String} result The resulting minified source.
+   */
+  function onUglify(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    result = postprocess(result);
+    this.uglified.source = result;
+    zlib.gzip(result, onUglifyGzip.bind(this));
+  }
+
+  /**
+   * The UglifyJS `gzip` callback.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {Buffer} result The resulting gzipped source.
+   */
+  function onUglifyGzip(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    if (result != null) {
+      if (!this.isSilent) {
+        console.log('Done. Size: %d bytes.', result.length);
+      }
+      this.uglified.gzip = result;
+    }
+    // minify the already Closure Compiler simple optimized source using UglifyJS
+    var modes = this.modes;
+    if (modes.indexOf('hybrid') > -1) {
+      if (modes.indexOf('simple') > -1) {
+        uglify.call(this, this.compiled.simple.source, 'hybrid (simple)', onSimpleHybrid.bind(this));
+      } else if (modes.indexOf('advanced') > -1) {
+        onSimpleHybridGzip.call(this);
+      }
+    } else {
+      onComplete.call(this);
+    }
+  }
+
+  /**
+   * The hybrid callback for simple optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {String} result The resulting minified source.
+   */
+  function onSimpleHybrid(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    result = postprocess(result);
+    this.hybrid.simple.source = result;
+    zlib.gzip(result, onSimpleHybridGzip.bind(this));
+  }
+
+  /**
+   * The hybrid `gzip` callback for simple optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {Buffer} result The resulting gzipped source.
+   */
+  function onSimpleHybridGzip(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    if (result != null) {
+      if (!this.isSilent) {
+        console.log('Done. Size: %d bytes.', result.length);
+      }
+      this.hybrid.simple.gzip = result;
+    }
+    // minify the already Closure Compiler advance optimized source using UglifyJS
+    if (this.modes.indexOf('advanced') > -1) {
+      uglify.call(this, this.compiled.advanced.source, 'hybrid (advanced)', onAdvancedHybrid.bind(this));
+    } else {
+      onComplete.call(this);
+    }
+  }
+
+  /**
+   * The hybrid callback for advanced optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {String} result The resulting minified source.
+   */
+  function onAdvancedHybrid(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    result = postprocess(result);
+    this.hybrid.advanced.source = result;
+    zlib.gzip(result, onAdvancedHybridGzip.bind(this));
+  }
+
+  /**
+   * The hybrid `gzip` callback for advanced optimizations.
+   *
+   * @private
+   * @param {Object|Undefined} exception The error object.
+   * @param {Buffer} result The resulting gzipped source.
+   */
+  function onAdvancedHybridGzip(exception, result) {
+    if (exception) {
+      throw exception;
+    }
+    if (result != null) {
+      if (!this.isSilent) {
+        console.log('Done. Size: %d bytes.', result.length);
+      }
+      this.hybrid.advanced.gzip = result;
+    }
+    // finish by choosing the smallest compressed file
+    onComplete.call(this);
+  }
+
+  /**
+   * The callback executed after the source is minified and gzipped.
+   *
+   * @private
+   */
+  function onComplete() {
+    var compiledSimple = this.compiled.simple,
+        compiledAdvanced = this.compiled.advanced,
+        uglified = this.uglified,
+        hybridSimple = this.hybrid.simple,
+        hybridAdvanced = this.hybrid.advanced;
+
+    var objects = [
+      compiledSimple,
+      compiledAdvanced,
+      uglified,
+      hybridSimple,
+      hybridAdvanced
+    ];
+
+    var gzips = objects
+      .map(function(data) { return data.gzip; })
+      .filter(Boolean);
+
+    // select the smallest gzipped file and use its minified counterpart as the
+    // official minified release (ties go to the Closure Compiler)
+    var min = gzips.reduce(function(min, gzip) {
+      var length = gzip.length;
+      return min > length ? length : min;
+    }, Infinity);
+
+    // pass the minified source to the "onComplete" callback
+    objects.some(function(data) {
+      var gzip = data.gzip;
+      if (gzip && gzip.length == min) {
+        data.outputPath = this.outputPath;
+        this.onComplete(data);
+        return true;
+      }
+    }, this);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose `minify`
+  if (module != require.main) {
+    module.exports = minify;
+  }
+  else {
+    // read the Lo-Dash source file from the first argument if the script
+    // was invoked directly (e.g. `node minify.js source.js`) and write to
+    // `<filename>.min.js`
+    (function() {
+      var options = process.argv;
+      if (options.length < 3) {
+        return;
+      }
+      minify(options);
+    }());
+  }
+}());
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/post-compile.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/post-compile.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/post-compile.js	(revision 533)
@@ -0,0 +1,79 @@
+#!/usr/bin/env node
+;(function() {
+  'use strict';
+
+  /** The Node filesystem module */
+  var fs = require('fs');
+
+  /** The minimal license/copyright template */
+  var licenseTemplate = [
+    '/**',
+    ' * @license',
+    ' * Lo-Dash <%= VERSION %> lodash.com/license',
+    ' * Underscore.js 1.4.4 underscorejs.org/LICENSE',
+    ' */'
+  ].join('\n');
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Post-process a given minified Lo-Dash `source`, preparing it for
+   * deployment.
+   *
+   * @param {String} source The source to process.
+   * @returns {String} Returns the processed source.
+   */
+  function postprocess(source) {
+    // remove copyright header
+    source = source.replace(/^\/\**[\s\S]+?\*\/\n/, '');
+
+    // correct overly aggressive Closure Compiler advanced optimizations
+    source = source
+      .replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}')
+      .replace(/(document[^&]+&&)\s*(?:\w+|!\d)/, '$1!({toString:0}+"")');
+
+    // flip `typeof` expressions to help optimize Safari and
+    // correct the AMD module definition for AMD build optimizers
+    // (e.g. from `"number" == typeof x` to `typeof x == "number")
+    source = source.replace(/(\w)?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.\w]+(?!\[)))/g, function(match, other, type, equality, expression) {
+      return (other ? other + ' ' : '') + expression + equality + type;
+    });
+
+    // add trailing semicolon
+    if (source) {
+      source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
+    }
+    // exit early if version snippet isn't found
+    var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
+    if (!snippet) {
+      return source;
+    }
+    // add new copyright header
+    var version = snippet[2];
+    source = licenseTemplate.replace('<%= VERSION %>', version) + '\n;' + source;
+
+    return source;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose `postprocess`
+  if (module != require.main) {
+    module.exports = postprocess;
+  }
+  else {
+    // read the Lo-Dash source file from the first argument if the script
+    // was invoked directly (e.g. `node post-compile.js source.js`) and write to
+    // the same file
+    (function() {
+      var options = process.argv;
+      if (options.length < 3) {
+        return;
+      }
+      var filePath = options[options.length - 1],
+          source = fs.readFileSync(filePath, 'utf8');
+
+      fs.writeFileSync(filePath, postprocess(source), 'utf8');
+    }());
+  }
+}());
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/pre-compile.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/pre-compile.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build/pre-compile.js	(revision 533)
@@ -0,0 +1,382 @@
+#!/usr/bin/env node
+;(function() {
+  'use strict';
+
+  /** The Node filesystem module */
+  var fs = require('fs');
+
+  /** Used to minify variables embedded in compiled strings */
+  var compiledVars = [
+    'args',
+    'argsIndex',
+    'argsLength',
+    'callback',
+    'collection',
+    'createCallback',
+    'ctor',
+    'guard',
+    'hasOwnProperty',
+    'index',
+    'isArguments',
+    'isArray',
+    'isString',
+    'iterable',
+    'length',
+    'nativeKeys',
+    'object',
+    'objectTypes',
+    'ownIndex',
+    'ownProps',
+    'result',
+    'skipProto',
+    'source',
+    'thisArg'
+  ];
+
+  /** Used to minify `compileIterator` option properties */
+  var iteratorOptions = [
+    'args',
+    'arrays',
+    'bottom',
+    'firstArg',
+    'hasDontEnumBug',
+    'hasEnumPrototype',
+    'isKeysFast',
+    'loop',
+    'nonEnumArgs',
+    'noCharByIndex',
+    'shadowed',
+    'top',
+    'useHas'
+  ];
+
+  /** Used to minify variables and string values to a single character */
+  var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
+  minNames.push.apply(minNames, minNames.map(function(value) {
+    return value + value;
+  }));
+
+  /** Used to protect the specified properties from getting minified */
+  var propWhitelist = [
+    '_',
+    '__wrapped__',
+    'after',
+    'all',
+    'amd',
+    'any',
+    'assign',
+    'at',
+    'attachEvent',
+    'bind',
+    'bindAll',
+    'bindKey',
+    'clearTimeout',
+    'clone',
+    'cloneDeep',
+    'collect',
+    'compact',
+    'compose',
+    'contains',
+    'countBy',
+    'criteria',
+    'debounce',
+    'defaults',
+    'defer',
+    'delay',
+    'detect',
+    'difference',
+    'drop',
+    'each',
+    'environment',
+    'escape',
+    'evaluate',
+    'every',
+    'exports',
+    'extend',
+    'filter',
+    'find',
+    'first',
+    'flatten',
+    'foldl',
+    'foldr',
+    'forEach',
+    'forIn',
+    'forOwn',
+    'functions',
+    'global',
+    'groupBy',
+    'has',
+    'head',
+    'imports',
+    'identity',
+    'include',
+    'index',
+    'indexOf',
+    'initial',
+    'inject',
+    'interpolate',
+    'intersection',
+    'invert',
+    'invoke',
+    'isArguments',
+    'isArray',
+    'isBoolean',
+    'isDate',
+    'isElement',
+    'isEmpty',
+    'isEqual',
+    'isEqual',
+    'isFinite',
+    'isFinite',
+    'isFunction',
+    'isNaN',
+    'isNull',
+    'isNumber',
+    'isObject',
+    'isPlainObject',
+    'isRegExp',
+    'isString',
+    'isUndefined',
+    'keys',
+    'last',
+    'lastIndexOf',
+    'map',
+    'max',
+    'memoize',
+    'merge',
+    'methods',
+    'min',
+    'mixin',
+    'noConflict',
+    'object',
+    'omit',
+    'once',
+    'opera',
+    'pairs',
+    'partial',
+    'partialRight',
+    'pick',
+    'pluck',
+    'random',
+    'range',
+    'reduce',
+    'reduceRight',
+    'reject',
+    'rest',
+    'result',
+    'select',
+    'setImmediate',
+    'setTimeout',
+    'shuffle',
+    'size',
+    'some',
+    'sortBy',
+    'sortedIndex',
+    'source',
+    'tail',
+    'take',
+    'tap',
+    'template',
+    'templateSettings',
+    'throttle',
+    'times',
+    'toArray',
+    'unescape',
+    'union',
+    'uniq',
+    'unique',
+    'uniqueId',
+    'value',
+    'values',
+    'variable',
+    'VERSION',
+    'where',
+    'without',
+    'wrap',
+    'zip',
+
+    // properties used by the `backbone` and `underscore` builds
+    '__chain__',
+    'chain',
+    'findWhere'
+  ];
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Pre-process a given Lo-Dash `source`, preparing it for minification.
+   *
+   * @param {String} [source=''] The source to process.
+   * @param {Object} [options={}] The options object.
+   * @returns {String} Returns the processed source.
+   */
+  function preprocess(source, options) {
+    source || (source = '');
+    options || (options = {});
+
+    // remove unrecognized JSDoc tags so the Closure Compiler won't complain
+    source = source.replace(/@(?:alias|category)\b.*/g, '');
+
+    if (options.isTemplate) {
+      return source;
+    }
+    // add brackets to whitelisted properties so the Closure Compiler won't mung them
+    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
+    source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), function(match, prop) {
+      return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
+    });
+
+    // remove brackets from `_.escape()` in `_.template`
+    source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
+
+    // remove brackets from `collection.indexOf` in `_.contains`
+    source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
+
+    // remove brackets from `result[length].value` in `_.sortBy`
+    source = source.replace("result[length]['value']", 'result[length].value');
+
+    // remove whitespace from string literals
+    source = source.replace(/^([ "'\w]+:)? *"[^"\\\n]*(?:\\.[^"\\\n]*)*"|'[^'\\\n]*(?:\\.[^'\\\n]*)*'/gm, function(string, captured) {
+      // remove object literal property name
+      if (/:$/.test(captured)) {
+        string = string.slice(captured.length);
+      }
+      // avoids removing the '\n' of the `stringEscapes` object
+      string = string.replace(/\[object |delete |else (?!{)|function | in |return\s+[\w"']|throw |typeof |use strict|var |@ |(["'])\\n\1|\\\\n|\\n|\s+/g, function(match) {
+        return match == false || match == '\\n' ? '' : match;
+      });
+      // prepend object literal property name
+      return (captured || '') + string;
+    });
+
+    // remove whitespace from `_.template` related regexes
+    source = source.replace(/reEmptyString\w+ *=.+/g, function(match) {
+      return match.replace(/ |\\n/g, '');
+    });
+
+    // remove newline from double-quoted strings in `_.template`
+    source = source
+      .replace('"__p += \'"', '"__p+=\'"')
+      .replace('"\';\n"', '"\';"')
+
+    // remove debug sourceURL use in `_.template`
+    source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
+
+    // minify internal properties used by 'compareAscending' and `_.sortBy`
+    (function() {
+      var properties = ['criteria', 'index', 'value'],
+          snippets = source.match(/( +)function (?:compareAscending|sortBy)\b[\s\S]+?\n\1}/g);
+
+      if (!snippets) {
+        return;
+      }
+      snippets.forEach(function(snippet) {
+        var modified = snippet;
+
+        // minify properties
+        properties.forEach(function(property, index) {
+          var minName = minNames[index],
+              reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
+              reDotProp = RegExp('\\.' + property + '\\b', 'g'),
+              rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g');
+
+          modified = modified
+            .replace(reBracketProp, "['" + minName + "']")
+            .replace(reDotProp, "['" + minName + "']")
+            .replace(rePropColon, "$1'" + minName + "':");
+        });
+
+        // replace with modified snippet
+        source = source.replace(snippet, modified);
+      });
+    }());
+
+    // minify all compilable snippets
+    var snippets = source.match(
+      RegExp([
+        // match the `iteratorTemplate`
+        '( +)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
+        // match methods created by `createIterator` calls
+        'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]+?\\);\\n',
+        // match variables storing `createIterator` options
+        '( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
+        // match the the `createIterator` function
+        '( +)function createIterator\\b[\\s\\S]+?\\n\\3}'
+      ].join('|'), 'g')
+    );
+
+    // exit early if no compilable snippets
+    if (!snippets) {
+      return source;
+    }
+
+    snippets.forEach(function(snippet, index) {
+      var isCreateIterator = /function createIterator\b/.test(snippet),
+          isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
+          modified = snippet;
+
+      // add brackets to iterator option properties so the Closure Compiler won't mung them
+      modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), function(match, prop) {
+        return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
+      });
+
+      if (isCreateIterator) {
+        // clip before the `factory` call to avoid minifying its arguments
+        source = source.replace(snippet, modified);
+        snippet = modified = modified.replace(/return factory\([\s\S]+$/, '');
+      }
+      // minify `createIterator` option property names
+      iteratorOptions.forEach(function(property, index) {
+        var minName = minNames[index];
+
+        // minify variables in `iteratorTemplate` or property names in everything else
+        modified = isIteratorTemplate
+          ? modified.replace(RegExp('\\b' + property + '\\b', 'g'), minName)
+          : modified.replace(RegExp("'" + property + "'", 'g'), "'" + minName + "'");
+      });
+
+      // minify snippet variables / arguments
+      compiledVars.forEach(function(variable, index) {
+        var minName = minNames[index];
+
+        // ensure properties in compiled strings aren't minified
+        modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minName);
+
+        // correct `typeof` values
+        if (/^(?:boolean|function|object|number|string|undefined)$/.test(variable)) {
+          modified = modified.replace(RegExp("(typeof [^']+')" + minName + "'", 'g'), '$1' + variable + "'");
+        }
+      });
+
+      // replace with modified snippet
+      source = source.replace(snippet, modified);
+    });
+
+    return source;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose `preprocess`
+  if (module != require.main) {
+    module.exports = preprocess;
+  }
+  else {
+    // read the Lo-Dash source file from the first argument if the script
+    // was invoked directly (e.g. `node pre-compile.js source.js`) and write to
+    // the same file
+    (function() {
+      var options = process.argv;
+      if (options.length < 3) {
+        return;
+      }
+      var filePath = options[options.length - 1],
+          isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
+          source = fs.readFileSync(filePath, 'utf8');
+
+      fs.writeFileSync(filePath, preprocess(source, {
+        'isTemplate': isTemplate
+      }), 'utf8');
+    }());
+  }
+}());
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js	(revision 533)
@@ -0,0 +1,5152 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 (Custom Build) <http://lodash.com/>
+ * Build: `lodash -o ./dist/lodash.compat.js`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function(window, undefined) {
+
+  /** Detect free variable `exports` */
+  var freeExports = typeof exports == 'object' && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
+
+  /** Detect free variable `global` and use it as `window` */
+  var freeGlobal = typeof global == 'object' && global;
+  if (freeGlobal.global === freeGlobal) {
+    window = freeGlobal;
+  }
+
+  /** Used for array and object method references */
+  var arrayRef = [],
+      objectRef = {};
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = objectRef;
+
+  /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
+  var largeArraySize = 30;
+
+  /** Used to restore the original `_` reference in `noConflict` */
+  var oldDash = window._;
+
+  /** Used to match HTML entities */
+  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detect if a method is native */
+  var reNative = RegExp('^' +
+    (objectRef.valueOf + '')
+      .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+      .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
+  );
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to match HTML characters */
+  var reUnescapedHtml = /[&<>"']/g;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to fix the JScript [[DontEnum]] bug */
+  var shadowed = [
+    'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+    'toLocaleString', 'toString', 'valueOf'
+  ];
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** Native method shortcuts */
+  var ceil = Math.ceil,
+      concat = arrayRef.concat,
+      floor = Math.floor,
+      getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+      hasOwnProperty = objectRef.hasOwnProperty,
+      push = arrayRef.push,
+      toString = objectRef.toString;
+
+  /* Native method shortcuts for methods with the same name as other `lodash` methods */
+  var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
+      nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
+      nativeIsFinite = window.isFinite,
+      nativeIsNaN = window.isNaN,
+      nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+      nativeMax = Math.max,
+      nativeMin = Math.min,
+      nativeRandom = Math.random;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Detect various environments */
+  var isIeOpera = !!window.attachEvent,
+      isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
+
+  /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
+  var isBindFast = nativeBind && !isV8;
+
+  /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
+  var isKeysFast = nativeKeys && (isIeOpera || isV8);
+
+  /**
+   * Detect the JScript [[DontEnum]] bug:
+   *
+   * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+   * made non-enumerable as well.
+   */
+  var hasDontEnumBug;
+
+  /**
+   * Detect if a `prototype` properties are enumerable by default:
+   *
+   * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+   * (if the prototype or a property on the prototype has been set)
+   * incorrectly sets a function's `prototype` property [[Enumerable]]
+   * value to `true`.
+   */
+  var hasEnumPrototype;
+
+  /** Detect if own properties are iterated after inherited properties (IE < 9) */
+  var iteratesOwnLast;
+
+  /**
+   * Detect if `Array#shift` and `Array#splice` augment array-like objects
+   * incorrectly:
+   *
+   * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+   * and `splice()` functions that fail to remove the last element, `value[0]`,
+   * of array-like objects even though the `length` property is set to `0`.
+   * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+   * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+   */
+  var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
+    arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
+
+  /** Detect if `arguments` object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1) */
+  var nonEnumArgs = true;
+
+  (function() {
+    var props = [];
+    function ctor() { this.x = 1; }
+    ctor.prototype = { 'valueOf': 1, 'y': 1 };
+    for (var prop in new ctor) { props.push(prop); }
+    for (prop in arguments) { nonEnumArgs = !prop; }
+
+    hasDontEnumBug = !/valueOf/.test(props);
+    hasEnumPrototype = ctor.propertyIsEnumerable('prototype');
+    iteratesOwnLast = props[0] != 'x';
+  }(1));
+
+  /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */
+  var argsAreObjects = arguments.constructor == Object;
+
+  /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */
+  var noArgsClass = !isArguments(arguments);
+
+  /**
+   * Detect lack of support for accessing string characters by index:
+   *
+   * IE < 8 can't access characters by index and IE 8 can only access
+   * characters by index on string literals.
+   */
+  var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
+
+  /**
+   * Detect if a DOM node's [[Class]] is unresolvable (IE < 9)
+   * and that the JS engine won't error when attempting to coerce an object to
+   * a string without a `toString` function.
+   */
+  try {
+    var noNodeClass = toString.call(document) == objectClass && !({ 'toString': 0 } + '');
+  } catch(e) { }
+
+  /** Used to identify object classifications that `_.clone` supports */
+  var cloneableClasses = {};
+  cloneableClasses[funcClass] = false;
+  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
+  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
+  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
+
+  /** Used to lookup a built-in constructor by [[Class]] */
+  var ctorByClass = {};
+  ctorByClass[arrayClass] = Array;
+  ctorByClass[boolClass] = Boolean;
+  ctorByClass[dateClass] = Date;
+  ctorByClass[objectClass] = Object;
+  ctorByClass[numberClass] = Number;
+  ctorByClass[regexpClass] = RegExp;
+  ctorByClass[stringClass] = String;
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object, that wraps the given `value`, to enable method
+   * chaining.
+   *
+   * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+   * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+   * and `unshift`
+   *
+   * The chainable wrapper functions are:
+   * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
+   * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
+   * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
+   * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
+   * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+   * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
+   * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
+   * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
+   *
+   * The non-chainable wrapper functions are:
+   * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
+   * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
+   * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
+   * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
+   * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
+   * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
+   *
+   * The wrapper functions `first` and `last` return wrapped values when `n` is
+   * passed, otherwise they return unwrapped values.
+   *
+   * @name _
+   * @constructor
+   * @category Chaining
+   * @param {Mixed} value The value to wrap in a `lodash` instance.
+   * @returns {Object} Returns a `lodash` instance.
+   */
+  function lodash(value) {
+    // exit early if already wrapped, even if wrapped by a different `lodash` constructor
+    if (value && typeof value == 'object' && value.__wrapped__) {
+      return value;
+    }
+    // allow invoking `lodash` without the `new` operator
+    if (!(this instanceof lodash)) {
+      return new lodash(value);
+    }
+    this.__wrapped__ = value;
+  }
+
+  /**
+   * By default, the template delimiters used by Lo-Dash are similar to those in
+   * embedded Ruby (ERB). Change the following template settings to use alternative
+   * delimiters.
+   *
+   * @static
+   * @memberOf _
+   * @type Object
+   */
+  lodash.templateSettings = {
+
+    /**
+     * Used to detect `data` property values to be HTML-escaped.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'escape': /<%-([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect code to be evaluated.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'evaluate': /<%([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect `data` property values to inject.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'interpolate': reInterpolate,
+
+    /**
+     * Used to reference the data object in the template text.
+     *
+     * @memberOf _.templateSettings
+     * @type String
+     */
+    'variable': '',
+
+    /**
+     * Used to import variables into the compiled template.
+     *
+     * @memberOf _.templateSettings
+     * @type Object
+     */
+    'imports': {
+
+      /**
+       * A reference to the `lodash` function.
+       *
+       * @memberOf _.templateSettings.imports
+       * @type Function
+       */
+      '_': lodash
+    }
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The template used to create iterator functions.
+   *
+   * @private
+   * @param {Obect} data The data object used to populate the text.
+   * @returns {String} Returns the interpolated text.
+   */
+  var iteratorTemplate = function(obj) {
+    
+    var __p = 'var index, iterable = ' +
+    (obj.firstArg ) +
+    ', result = iterable;\nif (!iterable) return result;\n' +
+    (obj.top ) +
+    ';\n';
+     if (obj.arrays) {
+    __p += 'var length = iterable.length; index = -1;\nif (' +
+    (obj.arrays ) +
+    ') {  ';
+     if (obj.noCharByIndex) {
+    __p += '\n  if (isString(iterable)) {\n    iterable = iterable.split(\'\')\n  }  ';
+     } ;
+    __p += '\n  while (++index < length) {\n    ' +
+    (obj.loop ) +
+    '\n  }\n}\nelse {  ';
+      } else if (obj.nonEnumArgs) {
+    __p += '\n  var length = iterable.length; index = -1;\n  if (length && isArguments(iterable)) {\n    while (++index < length) {\n      index += \'\';\n      ' +
+    (obj.loop ) +
+    '\n    }\n  } else {  ';
+     } ;
+    
+     if (obj.hasEnumPrototype) {
+    __p += '\n  var skipProto = typeof iterable == \'function\';\n  ';
+     } ;
+    
+     if (obj.isKeysFast && obj.useHas) {
+    __p += '\n  var ownIndex = -1,\n      ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n      length = ownProps.length;\n\n  while (++ownIndex < length) {\n    index = ownProps[ownIndex];\n    ';
+     if (obj.hasEnumPrototype) {
+    __p += 'if (!(skipProto && index == \'prototype\')) {\n  ';
+     } ;
+    __p += 
+    (obj.loop ) +
+    '';
+     if (obj.hasEnumPrototype) {
+    __p += '}\n';
+     } ;
+    __p += '  }  ';
+     } else {
+    __p += '\n  for (index in iterable) {';
+        if (obj.hasEnumPrototype || obj.useHas) {
+    __p += '\n    if (';
+          if (obj.hasEnumPrototype) {
+    __p += '!(skipProto && index == \'prototype\')';
+     }      if (obj.hasEnumPrototype && obj.useHas) {
+    __p += ' && ';
+     }      if (obj.useHas) {
+    __p += 'hasOwnProperty.call(iterable, index)';
+     }    ;
+    __p += ') {    ';
+     } ;
+    __p += 
+    (obj.loop ) +
+    ';    ';
+     if (obj.hasEnumPrototype || obj.useHas) {
+    __p += '\n    }';
+     } ;
+    __p += '\n  }  ';
+     } ;
+    
+     if (obj.hasDontEnumBug) {
+    __p += '\n\n  var ctor = iterable.constructor;\n    ';
+     for (var k = 0; k < 7; k++) {
+    __p += '\n  index = \'' +
+    (obj.shadowed[k] ) +
+    '\';\n  if (';
+          if (obj.shadowed[k] == 'constructor') {
+    __p += '!(ctor && ctor.prototype === iterable) && ';
+          } ;
+    __p += 'hasOwnProperty.call(iterable, index)) {\n    ' +
+    (obj.loop ) +
+    '\n  }    ';
+     } ;
+    
+     } ;
+    
+     if (obj.arrays || obj.nonEnumArgs) {
+    __p += '\n}';
+     } ;
+    __p += 
+    (obj.bottom ) +
+    ';\nreturn result';
+    
+    
+    return __p
+  };
+
+  /** Reusable iterator options for `assign` and `defaults` */
+  var defaultsIteratorOptions = {
+    'args': 'object, source, guard',
+    'top':
+      'var args = arguments,\n' +
+      '    argsIndex = 0,\n' +
+      "    argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
+      'while (++argsIndex < argsLength) {\n' +
+      '  iterable = args[argsIndex];\n' +
+      '  if (iterable && objectTypes[typeof iterable]) {',
+    'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
+    'bottom': '  }\n}'
+  };
+
+  /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
+  var eachIteratorOptions = {
+    'args': 'collection, callback, thisArg',
+    'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
+    'arrays': "typeof length == 'number'",
+    'loop': 'if (callback(iterable[index], index, collection) === false) return result'
+  };
+
+  /** Reusable iterator options for `forIn` and `forOwn` */
+  var forOwnIteratorOptions = {
+    'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
+    'arrays': false
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function optimized to search large arrays for a given `value`,
+   * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @param {Number} [largeSize=30] The length at which an array is considered large.
+   * @returns {Boolean} Returns `true`, if `value` is found, else `false`.
+   */
+  function cachedContains(array, fromIndex, largeSize) {
+    fromIndex || (fromIndex = 0);
+
+    var length = array.length,
+        isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
+
+    if (isLarge) {
+      var cache = {},
+          index = fromIndex - 1;
+
+      while (++index < length) {
+        // manually coerce `value` to a string because `hasOwnProperty`, in some
+        // older versions of Firefox, coerces objects incorrectly
+        var key = array[index] + '';
+        (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
+      }
+    }
+    return function(value) {
+      if (isLarge) {
+        var key = value + '';
+        return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
+      }
+      return indexOf(array, value, fromIndex) > -1;
+    }
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default `callback` when a given
+   * `collection` is a string value.
+   *
+   * @private
+   * @param {String} value The character to inspect.
+   * @returns {Number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` values, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {Number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ai = a.index,
+        bi = b.index;
+
+    a = a.criteria;
+    b = b.criteria;
+
+    // ensure a stable sort in V8 and other engines
+    // http://code.google.com/p/v8/issues/detail?id=90
+    if (a !== b) {
+      if (a > b || typeof a == 'undefined') {
+        return 1;
+      }
+      if (a < b || typeof b == 'undefined') {
+        return -1;
+      }
+    }
+    return ai < bi ? -1 : 1;
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this` binding
+   * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
+   * bound function.
+   *
+   * @private
+   * @param {Function|String} func The function to bind or the method name.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Array} partialArgs An array of arguments to be partially applied.
+   * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
+   * @returns {Function} Returns the new bound function.
+   */
+  function createBound(func, thisArg, partialArgs, rightIndicator) {
+    var isFunc = isFunction(func),
+        isPartial = !partialArgs,
+        key = thisArg;
+
+    // juggle arguments
+    if (isPartial) {
+      partialArgs = thisArg;
+    }
+    if (!isFunc) {
+      thisArg = func;
+    }
+
+    function bound() {
+      // `Function#bind` spec
+      // http://es5.github.com/#x15.3.4.5
+      var args = arguments,
+          thisBinding = isPartial ? this : thisArg;
+
+      if (!isFunc) {
+        func = thisArg[key];
+      }
+      if (partialArgs.length) {
+        args = args.length
+          ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
+          : partialArgs;
+      }
+      if (this instanceof bound) {
+        // ensure `new bound` is an instance of `bound` and `func`
+        noop.prototype = func.prototype;
+        thisBinding = new noop;
+        noop.prototype = null;
+
+        // mimic the constructor's `return` behavior
+        // http://es5.github.com/#x13.2.2
+        var result = func.apply(thisBinding, args);
+        return isObject(result) ? result : thisBinding;
+      }
+      return func.apply(thisBinding, args);
+    }
+    return bound;
+  }
+
+  /**
+   * Produces a callback bound to an optional `thisArg`. If `func` is a property
+   * name, the created callback will return the property value for a given element.
+   * If `func` is an object, the created callback will return `true` for elements
+   * that contain the equivalent object properties, otherwise it will return `false`.
+   *
+   * @private
+   * @param {Mixed} [func=identity] The value to convert to a callback.
+   * @param {Mixed} [thisArg] The `this` binding of the created callback.
+   * @param {Number} [argCount=3] The number of arguments the callback accepts.
+   * @returns {Function} Returns a callback function.
+   */
+  function createCallback(func, thisArg, argCount) {
+    if (func == null) {
+      return identity;
+    }
+    var type = typeof func;
+    if (type != 'function') {
+      if (type != 'object') {
+        return function(object) {
+          return object[func];
+        };
+      }
+      var props = keys(func);
+      return function(object) {
+        var length = props.length,
+            result = false;
+        while (length--) {
+          if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+    if (typeof thisArg != 'undefined') {
+      if (argCount === 1) {
+        return function(value) {
+          return func.call(thisArg, value);
+        };
+      }
+      if (argCount === 2) {
+        return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+      }
+      if (argCount === 4) {
+        return function(accumulator, value, index, object) {
+          return func.call(thisArg, accumulator, value, index, object);
+        };
+      }
+      return function(value, index, object) {
+        return func.call(thisArg, value, index, object);
+      };
+    }
+    return func;
+  }
+
+  /**
+   * Creates compiled iteration functions.
+   *
+   * @private
+   * @param {Object} [options1, options2, ...] The compile options object(s).
+   *  arrays - A string of code to determine if the iterable is an array or array-like.
+   *  useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
+   *  args - A string of comma separated arguments the iteration function will accept.
+   *  top - A string of code to execute before the iteration branches.
+   *  loop - A string of code to execute in the object loop.
+   *  bottom - A string of code to execute after the iteration branches.
+   *
+   * @returns {Function} Returns the compiled function.
+   */
+  function createIterator() {
+    var data = {
+      // support properties
+      'hasDontEnumBug': hasDontEnumBug,
+      'hasEnumPrototype': hasEnumPrototype,
+      'isKeysFast': isKeysFast,
+      'nonEnumArgs': nonEnumArgs,
+      'noCharByIndex': noCharByIndex,
+      'shadowed': shadowed,
+
+      // iterator options
+      'arrays': 'isArray(iterable)',
+      'bottom': '',
+      'loop': '',
+      'top': '',
+      'useHas': true
+    };
+
+    // merge options into a template data object
+    for (var object, index = 0; object = arguments[index]; index++) {
+      for (var key in object) {
+        data[key] = object[key];
+      }
+    }
+    var args = data.args;
+    data.firstArg = /^[^,]+/.exec(args)[0];
+
+    // create the function factory
+    var factory = Function(
+        'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
+        'objectTypes, nativeKeys',
+      'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
+    );
+    // return the compiled function
+    return factory(
+      createCallback, hasOwnProperty, isArguments, isArray, isString,
+      objectTypes, nativeKeys
+    );
+  }
+
+  /**
+   * A function compiled to iterate `arguments` objects, arrays, objects, and
+   * strings consistenly across environments, executing the `callback` for each
+   * element in the `collection`. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, index|key, collection). Callbacks may exit
+   * iteration early by explicitly returning `false`.
+   *
+   * @private
+   * @type Function
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   */
+  var each = createIterator(eachIteratorOptions);
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Used by `escape` to convert characters to HTML entities.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeHtmlChar(match) {
+    return htmlEscapes[match];
+  }
+
+  /**
+   * Checks if `value` is a DOM node in IE < 9.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
+   */
+  function isNode(value) {
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings
+    return typeof value.toString != 'function' && typeof (value + '') == 'string';
+  }
+
+  /**
+   * A no-operation function.
+   *
+   * @private
+   */
+  function noop() {
+    // no operation performed
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used, instead of `Array#slice`, to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|String} collection The collection to slice.
+   * @param {Number} start The start index.
+   * @param {Number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /**
+   * Used by `unescape` to convert HTML entities to characters.
+   *
+   * @private
+   * @param {String} match The matched character to unescape.
+   * @returns {String} Returns the unescaped character.
+   */
+  function unescapeHtmlChar(match) {
+    return htmlUnescapes[match];
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if `value` is an `arguments` object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
+   * @example
+   *
+   * (function() { return _.isArguments(arguments); })(1, 2, 3);
+   * // => true
+   *
+   * _.isArguments([1, 2, 3]);
+   * // => false
+   */
+  function isArguments(value) {
+    return toString.call(value) == argsClass;
+  }
+  // fallback for browsers that can't detect `arguments` objects by [[Class]]
+  if (noArgsClass) {
+    isArguments = function(value) {
+      return value ? hasOwnProperty.call(value, 'callee') : false;
+    };
+  }
+
+  /**
+   * Iterates over `object`'s own and inherited enumerable properties, executing
+   * the `callback` for each property. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, key, object). Callbacks may exit iteration
+   * early by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * function Dog(name) {
+   *   this.name = name;
+   * }
+   *
+   * Dog.prototype.bark = function() {
+   *   alert('Woof, woof!');
+   * };
+   *
+   * _.forIn(new Dog('Dagny'), function(value, key) {
+   *   alert(key);
+   * });
+   * // => alerts 'name' and 'bark' (order is not guaranteed)
+   */
+  var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
+    'useHas': false
+  });
+
+  /**
+   * Iterates over an object's own enumerable properties, executing the `callback`
+   * for each property. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
+   * returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+   *   alert(key);
+   * });
+   * // => alerts '0', '1', and 'length' (order is not guaranteed)
+   */
+  var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
+
+  /**
+   * Checks if `value` is an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
+   * @example
+   *
+   * (function() { return _.isArray(arguments); })();
+   * // => false
+   *
+   * _.isArray([1, 2, 3]);
+   * // => true
+   */
+  var isArray = nativeIsArray || function(value) {
+    // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
+    // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
+    return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass;
+  };
+
+  /**
+   * Creates an array composed of the own enumerable property names of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   * @example
+   *
+   * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => ['one', 'two', 'three'] (order is not guaranteed)
+   */
+  var keys = !nativeKeys ? shimKeys : function(object) {
+    if (!isObject(object)) {
+      return [];
+    }
+    if ((hasEnumPrototype && typeof object == 'function') ||
+        (nonEnumArgs && object.length && isArguments(object))) {
+      return shimKeys(object);
+    }
+    return nativeKeys(object);
+  };
+
+  /**
+   * A fallback implementation of `isPlainObject` that checks if a given `value`
+   * is an object created by the `Object` constructor, assuming objects created
+   * by the `Object` constructor have no inherited enumerable properties and that
+   * there are no `Object.prototype` extensions.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   */
+  function shimIsPlainObject(value) {
+    // avoid non-objects and false positives for `arguments` objects
+    var result = false;
+    if (!(value && typeof value == 'object') || isArguments(value)) {
+      return result;
+    }
+    // check that the constructor is `Object` (i.e. `Object instanceof Object`)
+    var ctor = value.constructor;
+    if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) {
+      // IE < 9 iterates inherited properties before own properties. If the first
+      // iterated property is an object's own property then there are no inherited
+      // enumerable properties.
+      if (iteratesOwnLast) {
+        forIn(value, function(value, key, object) {
+          result = !hasOwnProperty.call(object, key);
+          return false;
+        });
+        return result === false;
+      }
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return result === false || hasOwnProperty.call(value, result);
+    }
+    return result;
+  }
+
+  /**
+   * A fallback implementation of `Object.keys` that produces an array of the
+   * given object's own enumerable property names.
+   *
+   * @private
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   */
+  function shimKeys(object) {
+    var result = [];
+    forOwn(object, function(value, key) {
+      result.push(key);
+    });
+    return result;
+  }
+
+  /**
+   * Used to convert characters to HTML entities:
+   *
+   * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+   * don't require escaping in HTML and have no special meaning unless they're part
+   * of a tag or an unquoted attribute value.
+   * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+   */
+  var htmlEscapes = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#39;'
+  };
+
+  /** Used to convert HTML entities to characters */
+  var htmlUnescapes = invert(htmlEscapes);
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object. Subsequent sources will overwrite propery assignments of previous
+   * sources. If a `callback` function is passed, it will be executed to produce
+   * the assigned values. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @alias extend
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize assigning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * _.assign({ 'name': 'moe' }, { 'age': 40 });
+   * // => { 'name': 'moe', 'age': 40 }
+   *
+   * var defaults = _.partialRight(_.assign, function(a, b) {
+   *   return typeof a == 'undefined' ? b : a;
+   * });
+   *
+   * var food = { 'name': 'apple' };
+   * defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  var assign = createIterator(defaultsIteratorOptions, {
+    'top':
+      defaultsIteratorOptions.top.replace(';',
+        ';\n' +
+        "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
+        '  var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
+        "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
+        '  callback = args[--argsLength];\n' +
+        '}'
+      ),
+    'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
+  });
+
+  /**
+   * Creates a clone of `value`. If `deep` is `true`, nested objects will also
+   * be cloned, otherwise they will be assigned by reference. If a `callback`
+   * function is passed, it will be executed to produce the cloned values. If
+   * `callback` returns `undefined`, cloning will be handled by the method instead.
+   * The `callback` is bound to `thisArg` and invoked with one argument; (value).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to clone.
+   * @param {Boolean} [deep=false] A flag to indicate a deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
+   * @returns {Mixed} Returns the cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var shallow = _.clone(stooges);
+   * shallow[0] === stooges[0];
+   * // => true
+   *
+   * var deep = _.clone(stooges, true);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * _.mixin({
+   *   'clone': _.partialRight(_.clone, function(value) {
+   *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+   *   })
+   * });
+   *
+   * var clone = _.clone(document.body);
+   * clone.childNodes.length;
+   * // => 0
+   */
+  function clone(value, deep, callback, thisArg, stackA, stackB) {
+    var result = value;
+
+    // allows working with "Collections" methods without using their `callback`
+    // argument, `index|key`, for this method's `callback`
+    if (typeof deep == 'function') {
+      thisArg = callback;
+      callback = deep;
+      deep = false;
+    }
+    if (typeof callback == 'function') {
+      callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
+      result = callback(result);
+
+      var done = typeof result != 'undefined';
+      if (!done) {
+        result = value;
+      }
+    }
+    // inspect [[Class]]
+    var isObj = isObject(result);
+    if (isObj) {
+      var className = toString.call(result);
+      if (!cloneableClasses[className] || (noNodeClass && isNode(result))) {
+        return result;
+      }
+      var isArr = isArray(result);
+    }
+    // shallow clone
+    if (!isObj || !deep) {
+      return isObj && !done
+        ? (isArr ? slice(result) : assign({}, result))
+        : result;
+    }
+    var ctor = ctorByClass[className];
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        return done ? result : new ctor(+result);
+
+      case numberClass:
+      case stringClass:
+        return done ? result : new ctor(result);
+
+      case regexpClass:
+        return done ? result : ctor(result.source, reFlags.exec(result));
+    }
+    // check for circular references and return corresponding clone
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == value) {
+        return stackB[length];
+      }
+    }
+    // init cloned object
+    if (!done) {
+      result = isArr ? ctor(result.length) : {};
+
+      // add array properties assigned by `RegExp#exec`
+      if (isArr) {
+        if (hasOwnProperty.call(value, 'index')) {
+          result.index = value.index;
+        }
+        if (hasOwnProperty.call(value, 'input')) {
+          result.input = value.input;
+        }
+      }
+    }
+    // add the source value to the stack of traversed objects
+    // and associate it with its clone
+    stackA.push(value);
+    stackB.push(result);
+
+    // recursively populate clone (susceptible to call stack limits)
+    (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
+      result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
+    });
+
+    return result;
+  }
+
+  /**
+   * Creates a deep clone of `value`. If a `callback` function is passed, it will
+   * be executed to produce the cloned values. If `callback` returns the value it
+   * was passed, cloning will be handled by the method instead. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * Note: This function is loosely based on the structured clone algorithm. Functions
+   * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+   * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+   * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the deep cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var deep = _.cloneDeep(stooges);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * var view = {
+   *   'label': 'docs',
+   *   'node': element
+   * };
+   *
+   * var clone = _.cloneDeep(view, function(value) {
+   *   return _.isElement(value) ? value.cloneNode(true) : value;
+   * });
+   *
+   * clone.node == view.node;
+   * // => false
+   */
+  function cloneDeep(value, callback, thisArg) {
+    return clone(value, true, callback, thisArg);
+  }
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object for all destination properties that resolve to `undefined`. Once a
+   * property is set, additional defaults of the same property will be ignored.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param- {Object} [guard] Internally used to allow working with `_.reduce`
+   *  without using its callback's `key` and `object` arguments as sources.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var food = { 'name': 'apple' };
+   * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  var defaults = createIterator(defaultsIteratorOptions);
+
+  /**
+   * Creates a sorted array of all enumerable properties, own and inherited,
+   * of `object` that have function values.
+   *
+   * @static
+   * @memberOf _
+   * @alias methods
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names that have function values.
+   * @example
+   *
+   * _.functions(_);
+   * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+   */
+  function functions(object) {
+    var result = [];
+    forIn(object, function(value, key) {
+      if (isFunction(value)) {
+        result.push(key);
+      }
+    });
+    return result.sort();
+  }
+
+  /**
+   * Checks if the specified object `property` exists and is a direct property,
+   * instead of an inherited property.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to check.
+   * @param {String} property The property to check for.
+   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+   * @example
+   *
+   * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+   * // => true
+   */
+  function has(object, property) {
+    return object ? hasOwnProperty.call(object, property) : false;
+  }
+
+  /**
+   * Creates an object composed of the inverted keys and values of the given `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to invert.
+   * @returns {Object} Returns the created inverted object.
+   * @example
+   *
+   *  _.invert({ 'first': 'moe', 'second': 'larry' });
+   * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
+   */
+  function invert(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      result[object[key]] = key;
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is a boolean value.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
+   * @example
+   *
+   * _.isBoolean(null);
+   * // => false
+   */
+  function isBoolean(value) {
+    return value === true || value === false || toString.call(value) == boolClass;
+  }
+
+  /**
+   * Checks if `value` is a date.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
+   * @example
+   *
+   * _.isDate(new Date);
+   * // => true
+   */
+  function isDate(value) {
+    return value instanceof Date || toString.call(value) == dateClass;
+  }
+
+  /**
+   * Checks if `value` is a DOM element.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
+   * @example
+   *
+   * _.isElement(document.body);
+   * // => true
+   */
+  function isElement(value) {
+    return value ? value.nodeType === 1 : false;
+  }
+
+  /**
+   * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+   * length of `0` and objects with no own enumerable properties are considered
+   * "empty".
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Array|Object|String} value The value to inspect.
+   * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
+   * @example
+   *
+   * _.isEmpty([1, 2, 3]);
+   * // => false
+   *
+   * _.isEmpty({});
+   * // => true
+   *
+   * _.isEmpty('');
+   * // => true
+   */
+  function isEmpty(value) {
+    var result = true;
+    if (!value) {
+      return result;
+    }
+    var className = toString.call(value),
+        length = value.length;
+
+    if ((className == arrayClass || className == stringClass ||
+        className == argsClass || (noArgsClass && isArguments(value))) ||
+        (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+      return !length;
+    }
+    forOwn(value, function() {
+      return (result = false);
+    });
+    return result;
+  }
+
+  /**
+   * Performs a deep comparison between two values to determine if they are
+   * equivalent to each other. If `callback` is passed, it will be executed to
+   * compare values. If `callback` returns `undefined`, comparisons will be handled
+   * by the method instead. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (a, b).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} a The value to compare.
+   * @param {Mixed} b The other value to compare.
+   * @param {Function} [callback] The function to customize comparing values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
+   * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
+   * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
+   * @example
+   *
+   * var moe = { 'name': 'moe', 'age': 40 };
+   * var copy = { 'name': 'moe', 'age': 40 };
+   *
+   * moe == copy;
+   * // => false
+   *
+   * _.isEqual(moe, copy);
+   * // => true
+   *
+   * var words = ['hello', 'goodbye'];
+   * var otherWords = ['hi', 'goodbye'];
+   *
+   * _.isEqual(words, otherWords, function(a, b) {
+   *   var reGreet = /^(?:hello|hi)$/i,
+   *       aGreet = _.isString(a) && reGreet.test(a),
+   *       bGreet = _.isString(b) && reGreet.test(b);
+   *
+   *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+   * });
+   * // => true
+   */
+  function isEqual(a, b, callback, thisArg, stackA, stackB) {
+    // used to indicate that when comparing objects, `a` has at least the properties of `b`
+    var whereIndicator = callback === indicatorObject;
+    if (callback && !whereIndicator) {
+      callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
+      var result = callback(a, b);
+      if (typeof result != 'undefined') {
+        return !!result;
+      }
+    }
+    // exit early for identical values
+    if (a === b) {
+      // treat `+0` vs. `-0` as not equal
+      return a !== 0 || (1 / a == 1 / b);
+    }
+    var type = typeof a,
+        otherType = typeof b;
+
+    // exit early for unlike primitive values
+    if (a === a &&
+        (!a || (type != 'function' && type != 'object')) &&
+        (!b || (otherType != 'function' && otherType != 'object'))) {
+      return false;
+    }
+    // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
+    // http://es5.github.com/#x15.3.4.4
+    if (a == null || b == null) {
+      return a === b;
+    }
+    // compare [[Class]] names
+    var className = toString.call(a),
+        otherClass = toString.call(b);
+
+    if (className == argsClass) {
+      className = objectClass;
+    }
+    if (otherClass == argsClass) {
+      otherClass = objectClass;
+    }
+    if (className != otherClass) {
+      return false;
+    }
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        // coerce dates and booleans to numbers, dates to milliseconds and booleans
+        // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
+        return +a == +b;
+
+      case numberClass:
+        // treat `NaN` vs. `NaN` as equal
+        return a != +a
+          ? b != +b
+          // but treat `+0` vs. `-0` as not equal
+          : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+      case regexpClass:
+      case stringClass:
+        // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
+        // treat string primitives and their corresponding object instances as equal
+        return a == b + '';
+    }
+    var isArr = className == arrayClass;
+    if (!isArr) {
+      // unwrap any `lodash` wrapped values
+      if (a.__wrapped__ || b.__wrapped__) {
+        return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
+      }
+      // exit for functions and DOM nodes
+      if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) {
+        return false;
+      }
+      // in older versions of Opera, `arguments` objects have `Array` constructors
+      var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor,
+          ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor;
+
+      // non `Object` object instances with different constructors are not equal
+      if (ctorA != ctorB && !(
+            isFunction(ctorA) && ctorA instanceof ctorA &&
+            isFunction(ctorB) && ctorB instanceof ctorB
+          )) {
+        return false;
+      }
+    }
+    // assume cyclic structures are equal
+    // the algorithm for detecting cyclic structures is adapted from ES 5.1
+    // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == a) {
+        return stackB[length] == b;
+      }
+    }
+    var size = 0;
+    result = true;
+
+    // add `a` and `b` to the stack of traversed objects
+    stackA.push(a);
+    stackB.push(b);
+
+    // recursively compare objects and arrays (susceptible to call stack limits)
+    if (isArr) {
+      length = a.length;
+      size = b.length;
+
+      // compare lengths to determine if a deep comparison is necessary
+      result = size == a.length;
+      if (!result && !whereIndicator) {
+        return result;
+      }
+      // deep compare the contents, ignoring non-numeric properties
+      while (size--) {
+        var index = length,
+            value = b[size];
+
+        if (whereIndicator) {
+          while (index--) {
+            if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
+              break;
+            }
+          }
+        } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
+          break;
+        }
+      }
+      return result;
+    }
+    // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
+    // which, in this case, is more costly
+    forIn(b, function(value, key, b) {
+      if (hasOwnProperty.call(b, key)) {
+        // count the number of properties.
+        size++;
+        // deep compare each property value.
+        return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
+      }
+    });
+
+    if (result && !whereIndicator) {
+      // ensure both objects have the same number of properties
+      forIn(a, function(value, key, a) {
+        if (hasOwnProperty.call(a, key)) {
+          // `size` will be `-1` if `a` has more properties than `b`
+          return (result = --size > -1);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is, or can be coerced to, a finite number.
+   *
+   * Note: This is not the same as native `isFinite`, which will return true for
+   * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
+   * @example
+   *
+   * _.isFinite(-101);
+   * // => true
+   *
+   * _.isFinite('10');
+   * // => true
+   *
+   * _.isFinite(true);
+   * // => false
+   *
+   * _.isFinite('');
+   * // => false
+   *
+   * _.isFinite(Infinity);
+   * // => false
+   */
+  function isFinite(value) {
+    return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+  }
+
+  /**
+   * Checks if `value` is a function.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
+   * @example
+   *
+   * _.isFunction(_);
+   * // => true
+   */
+  function isFunction(value) {
+    return typeof value == 'function';
+  }
+  // fallback for older versions of Chrome and Safari
+  if (isFunction(/x/)) {
+    isFunction = function(value) {
+      return value instanceof Function || toString.call(value) == funcClass;
+    };
+  }
+
+  /**
+   * Checks if `value` is the language type of Object.
+   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
+   * @example
+   *
+   * _.isObject({});
+   * // => true
+   *
+   * _.isObject([1, 2, 3]);
+   * // => true
+   *
+   * _.isObject(1);
+   * // => false
+   */
+  function isObject(value) {
+    // check if the value is the ECMAScript language type of Object
+    // http://es5.github.com/#x8
+    // and avoid a V8 bug
+    // http://code.google.com/p/v8/issues/detail?id=2291
+    return value ? objectTypes[typeof value] : false;
+  }
+
+  /**
+   * Checks if `value` is `NaN`.
+   *
+   * Note: This is not the same as native `isNaN`, which will return `true` for
+   * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
+   * @example
+   *
+   * _.isNaN(NaN);
+   * // => true
+   *
+   * _.isNaN(new Number(NaN));
+   * // => true
+   *
+   * isNaN(undefined);
+   * // => true
+   *
+   * _.isNaN(undefined);
+   * // => false
+   */
+  function isNaN(value) {
+    // `NaN` as a primitive is the only value that is not equal to itself
+    // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+    return isNumber(value) && value != +value
+  }
+
+  /**
+   * Checks if `value` is `null`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
+   * @example
+   *
+   * _.isNull(null);
+   * // => true
+   *
+   * _.isNull(undefined);
+   * // => false
+   */
+  function isNull(value) {
+    return value === null;
+  }
+
+  /**
+   * Checks if `value` is a number.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
+   * @example
+   *
+   * _.isNumber(8.4 * 5);
+   * // => true
+   */
+  function isNumber(value) {
+    return typeof value == 'number' || toString.call(value) == numberClass;
+  }
+
+  /**
+   * Checks if a given `value` is an object created by the `Object` constructor.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   * @example
+   *
+   * function Stooge(name, age) {
+   *   this.name = name;
+   *   this.age = age;
+   * }
+   *
+   * _.isPlainObject(new Stooge('moe', 40));
+   * // => false
+   *
+   * _.isPlainObject([1, 2, 3]);
+   * // => false
+   *
+   * _.isPlainObject({ 'name': 'moe', 'age': 40 });
+   * // => true
+   */
+  var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+    if (!(value && typeof value == 'object')) {
+      return false;
+    }
+    var valueOf = value.valueOf,
+        objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+    return objProto
+      ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
+      : shimIsPlainObject(value);
+  };
+
+  /**
+   * Checks if `value` is a regular expression.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
+   * @example
+   *
+   * _.isRegExp(/moe/);
+   * // => true
+   */
+  function isRegExp(value) {
+    return value instanceof RegExp || toString.call(value) == regexpClass;
+  }
+
+  /**
+   * Checks if `value` is a string.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
+   * @example
+   *
+   * _.isString('moe');
+   * // => true
+   */
+  function isString(value) {
+    return typeof value == 'string' || toString.call(value) == stringClass;
+  }
+
+  /**
+   * Checks if `value` is `undefined`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
+   * @example
+   *
+   * _.isUndefined(void 0);
+   * // => true
+   */
+  function isUndefined(value) {
+    return typeof value == 'undefined';
+  }
+
+  /**
+   * Recursively merges own enumerable properties of the source object(s), that
+   * don't resolve to `undefined`, into the destination object. Subsequent sources
+   * will overwrite propery assignments of previous sources. If a `callback` function
+   * is passed, it will be executed to produce the merged values of the destination
+   * and source properties. If `callback` returns `undefined`, merging will be
+   * handled by the method instead. The `callback` is bound to `thisArg` and
+   * invoked with two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize merging properties.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [deepIndicator] Internally used to indicate that `stackA`
+   *  and `stackB` are arrays of traversed objects instead of source objects.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate values with their
+   *  source counterparts.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var names = {
+   *   'stooges': [
+   *     { 'name': 'moe' },
+   *     { 'name': 'larry' }
+   *   ]
+   * };
+   *
+   * var ages = {
+   *   'stooges': [
+   *     { 'age': 40 },
+   *     { 'age': 50 }
+   *   ]
+   * };
+   *
+   * _.merge(names, ages);
+   * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
+   *
+   * var food = {
+   *   'fruits': ['apple'],
+   *   'vegetables': ['beet']
+   * };
+   *
+   * var otherFood = {
+   *   'fruits': ['banana'],
+   *   'vegetables': ['carrot']
+   * };
+   *
+   * _.merge(food, otherFood, function(a, b) {
+   *   return _.isArray(a) ? a.concat(b) : undefined;
+   * });
+   * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+   */
+  function merge(object, source, deepIndicator) {
+    var args = arguments,
+        index = 0,
+        length = 2;
+
+    if (!isObject(object)) {
+      return object;
+    }
+    if (deepIndicator === indicatorObject) {
+      var callback = args[3],
+          stackA = args[4],
+          stackB = args[5];
+    } else {
+      stackA = [];
+      stackB = [];
+
+      // allows working with `_.reduce` and `_.reduceRight` without
+      // using their `callback` arguments, `index|key` and `collection`
+      if (typeof deepIndicator != 'number') {
+        length = args.length;
+      }
+      if (length > 3 && typeof args[length - 2] == 'function') {
+        callback = createCallback(args[--length - 1], args[length--], 2);
+      } else if (length > 2 && typeof args[length - 1] == 'function') {
+        callback = args[--length];
+      }
+    }
+    while (++index < length) {
+      (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
+        var found,
+            isArr,
+            result = source,
+            value = object[key];
+
+        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+          // avoid merging previously merged cyclic sources
+          var stackLength = stackA.length;
+          while (stackLength--) {
+            if ((found = stackA[stackLength] == source)) {
+              value = stackB[stackLength];
+              break;
+            }
+          }
+          if (!found) {
+            value = isArr
+              ? (isArray(value) ? value : [])
+              : (isPlainObject(value) ? value : {});
+
+            if (callback) {
+              result = callback(value, source);
+              if (typeof result != 'undefined') {
+                value = result;
+              }
+            }
+            // add `source` and associated `value` to the stack of traversed objects
+            stackA.push(source);
+            stackB.push(value);
+
+            // recursively merge objects and arrays (susceptible to call stack limits)
+            if (!callback) {
+              value = merge(value, source, indicatorObject, callback, stackA, stackB);
+            }
+          }
+        }
+        else {
+          if (callback) {
+            result = callback(value, source);
+            if (typeof result == 'undefined') {
+              result = source;
+            }
+          }
+          if (typeof result != 'undefined') {
+            value = result;
+          }
+        }
+        object[key] = value;
+      });
+    }
+    return object;
+  }
+
+  /**
+   * Creates a shallow clone of `object` excluding the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a `callback` function is passed, it will be executed
+   * for each property in the `object`, omitting the properties `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
+   *  or the function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object without the omitted properties.
+   * @example
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, 'age');
+   * // => { 'name': 'moe' }
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
+   *   return typeof value == 'number';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function omit(object, callback, thisArg) {
+    var isFunc = typeof callback == 'function',
+        result = {};
+
+    if (isFunc) {
+      callback = createCallback(callback, thisArg);
+    } else {
+      var props = concat.apply(arrayRef, arguments);
+    }
+    forIn(object, function(value, key, object) {
+      if (isFunc
+            ? !callback(value, key, object)
+            : indexOf(props, key, 1) < 0
+          ) {
+        result[key] = value;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Creates a two dimensional array of the given object's key-value pairs,
+   * i.e. `[[key1, value1], [key2, value2]]`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns new array of key-value pairs.
+   * @example
+   *
+   * _.pairs({ 'moe': 30, 'larry': 40 });
+   * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
+   */
+  function pairs(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      var key = props[index];
+      result[index] = [key, object[key]];
+    }
+    return result;
+  }
+
+  /**
+   * Creates a shallow clone of `object` composed of the specified properties.
+   * Property names may be specified as individual arguments or as arrays of property
+   * names. If `callback` is passed, it will be executed for each property in the
+   * `object`, picking the properties `callback` returns truthy for. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
+   *  per iteration or properties to pick, either as individual arguments or arrays.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object composed of the picked properties.
+   * @example
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
+   * // => { 'name': 'moe' }
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
+   *   return key.charAt(0) != '_';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function pick(object, callback, thisArg) {
+    var result = {};
+    if (typeof callback != 'function') {
+      var index = 0,
+          props = concat.apply(arrayRef, arguments),
+          length = isObject(object) ? props.length : 0;
+
+      while (++index < length) {
+        var key = props[index];
+        if (key in object) {
+          result[key] = object[key];
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg);
+      forIn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result[key] = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array composed of the own enumerable property values of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => [1, 2, 3]
+   */
+  function values(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = object[props[index]];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array of elements from the specified indexes, or keys, of the
+   * `collection`. Indexes may be specified as individual arguments or as arrays
+   * of indexes.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Array|Number|String} [index1, index2, ...] The indexes of
+   *  `collection` to retrieve, either as individual arguments or arrays.
+   * @returns {Array} Returns a new array of elements corresponding to the
+   *  provided indexes.
+   * @example
+   *
+   * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+   * // => ['a', 'c', 'e']
+   *
+   * _.at(['moe', 'larry', 'curly'], 0, 2);
+   * // => ['moe', 'curly']
+   */
+  function at(collection) {
+    var index = -1,
+        props = concat.apply(arrayRef, slice(arguments, 1)),
+        length = props.length,
+        result = Array(length);
+
+    if (noCharByIndex && isString(collection)) {
+      collection = collection.split('');
+    }
+    while(++index < length) {
+      result[index] = collection[props[index]];
+    }
+    return result;
+  }
+
+  /**
+   * Checks if a given `target` element is present in a `collection` using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @alias include
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Mixed} target The value to check for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
+   * @example
+   *
+   * _.contains([1, 2, 3], 1);
+   * // => true
+   *
+   * _.contains([1, 2, 3], 1, 2);
+   * // => false
+   *
+   * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+   * // => true
+   *
+   * _.contains('curly', 'ur');
+   * // => true
+   */
+  function contains(collection, target, fromIndex) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = false;
+
+    fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+    if (typeof length == 'number') {
+      result = (isString(collection)
+        ? collection.indexOf(target, fromIndex)
+        : indexOf(collection, target, fromIndex)
+      ) > -1;
+    } else {
+      each(collection, function(value) {
+        if (++index >= fromIndex) {
+          return !(result = value === target);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the given `callback`. The corresponding value of each key
+   * is the number of times the key was returned by the `callback`. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy(['one', 'two', 'three'], 'length');
+   * // => { '3': 2, '5': 1 }
+   */
+  function countBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+    return result;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **all** elements of a
+   * `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias all
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if all elements pass the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.every([true, 1, null, 'yes'], Boolean);
+   * // => false
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.every(stooges, 'age');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.every(stooges, { 'age': 50 });
+   * // => false
+   */
+  function every(collection, callback, thisArg) {
+    var result = true;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (!(result = !!callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return (result = !!callback(value, index, collection));
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias select
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that passed the callback check.
+   * @example
+   *
+   * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [2, 4, 6]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.filter(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.filter(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   */
+  function filter(collection, callback, thisArg) {
+    var result = [];
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning the first that the `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias detect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the element that passed the callback check,
+   *  else `undefined`.
+   * @example
+   *
+   * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => 2
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },
+   *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * var veggie = _.find(food, { 'type': 'vegetable' });
+   * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
+   *
+   * // using "_.pluck" callback shorthand
+   * var healthy = _.find(food, 'organic');
+   * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
+   */
+  function find(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, index, collection) {
+      if (callback(value, index, collection)) {
+        result = value;
+        return false;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Iterates over a `collection`, executing the `callback` for each element in
+   * the `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection). Callbacks may exit iteration early
+   * by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias each
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   * @example
+   *
+   * _([1, 2, 3]).forEach(alert).join(',');
+   * // => alerts each number and returns '1,2,3'
+   *
+   * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
+   * // => alerts each number value (order is not guaranteed)
+   */
+  function forEach(collection, callback, thisArg) {
+    if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (callback(collection[index], index, collection) === false) {
+          break;
+        }
+      }
+    } else {
+      each(collection, callback, thisArg);
+    }
+    return collection;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the `callback`. The corresponding value of each key is
+   * an array of elements passed to `callback` that returned the key. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * // using "_.pluck" callback shorthand
+   * _.groupBy(['one', 'two', 'three'], 'length');
+   * // => { '3': ['one', 'two'], '5': ['three'] }
+   */
+  function groupBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+    return result;
+  }
+
+  /**
+   * Invokes the method named by `methodName` on each element in the `collection`,
+   * returning an array of the results of each invoked method. Additional arguments
+   * will be passed to each invoked method. If `methodName` is a function, it will
+   * be invoked for, and `this` bound to, each element in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|String} methodName The name of the method to invoke or
+   *  the function invoked per iteration.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+   * @returns {Array} Returns a new array of the results of each invoked method.
+   * @example
+   *
+   * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+   * // => [[1, 5, 7], [1, 2, 3]]
+   *
+   * _.invoke([123, 456], String.prototype.split, '');
+   * // => [['1', '2', '3'], ['4', '5', '6']]
+   */
+  function invoke(collection, methodName) {
+    var args = slice(arguments, 2),
+        index = -1,
+        isFunc = typeof methodName == 'function',
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+    });
+    return result;
+  }
+
+  /**
+   * Creates an array of values by running each element in the `collection`
+   * through the `callback`. The `callback` is bound to `thisArg` and invoked with
+   * three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias collect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * _.map([1, 2, 3], function(num) { return num * 3; });
+   * // => [3, 6, 9]
+   *
+   * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+   * // => [3, 6, 9] (order is not guaranteed)
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.map(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  function map(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    if (isArray(collection)) {
+      while (++index < length) {
+        result[index] = callback(collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, key, collection) {
+        result[++index] = callback(value, key, collection);
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the maximum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the maximum value.
+   * @example
+   *
+   * _.max([4, 2, 8, 6]);
+   * // => 8
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.max(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'larry', 'age': 50 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.max(stooges, 'age');
+   * // => { 'name': 'larry', 'age': 50 };
+   */
+  function max(collection, callback, thisArg) {
+    var computed = -Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value > result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = !callback && isString(collection)
+        ? charAtCallback
+        : createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current > computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the minimum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the minimum value.
+   * @example
+   *
+   * _.min([4, 2, 8, 6]);
+   * // => 2
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.min(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'moe', 'age': 40 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.min(stooges, 'age');
+   * // => { 'name': 'moe', 'age': 40 };
+   */
+  function min(collection, callback, thisArg) {
+    var computed = Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value < result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = !callback && isString(collection)
+        ? charAtCallback
+        : createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current < computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the value of a specified property from all elements in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {String} property The property to pluck.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.pluck(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  var pluck = map;
+
+  /**
+   * Reduces a `collection` to a value that is the accumulated result of running
+   * each element in the `collection` through the `callback`, where each successive
+   * `callback` execution consumes the return value of the previous execution.
+   * If `accumulator` is not passed, the first element of the `collection` will be
+   * used as the initial `accumulator` value. The `callback` is bound to `thisArg`
+   * and invoked with four arguments; (accumulator, value, index|key, collection).
+   *
+   * @static
+   * @memberOf _
+   * @alias foldl, inject
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var sum = _.reduce([1, 2, 3], function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+   *   result[key] = num * 3;
+   *   return result;
+   * }, {});
+   * // => { 'a': 3, 'b': 6, 'c': 9 }
+   */
+  function reduce(collection, callback, accumulator, thisArg) {
+    var noaccum = arguments.length < 3;
+    callback = createCallback(callback, thisArg, 4);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      if (noaccum) {
+        accumulator = collection[++index];
+      }
+      while (++index < length) {
+        accumulator = callback(accumulator, collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection)
+      });
+    }
+    return accumulator;
+  }
+
+  /**
+   * This method is similar to `_.reduce`, except that it iterates over a
+   * `collection` from right to left.
+   *
+   * @static
+   * @memberOf _
+   * @alias foldr
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var list = [[0, 1], [2, 3], [4, 5]];
+   * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+   * // => [4, 5, 2, 3, 0, 1]
+   */
+  function reduceRight(collection, callback, accumulator, thisArg) {
+    var iterable = collection,
+        length = collection ? collection.length : 0,
+        noaccum = arguments.length < 3;
+
+    if (typeof length != 'number') {
+      var props = keys(collection);
+      length = props.length;
+    } else if (noCharByIndex && isString(collection)) {
+      iterable = collection.split('');
+    }
+    callback = createCallback(callback, thisArg, 4);
+    forEach(collection, function(value, index, collection) {
+      index = props ? props[--length] : --length;
+      accumulator = noaccum
+        ? (noaccum = false, iterable[index])
+        : callback(accumulator, iterable[index], index, collection);
+    });
+    return accumulator;
+  }
+
+  /**
+   * The opposite of `_.filter`, this method returns the elements of a
+   * `collection` that `callback` does **not** return truthy for.
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that did **not** pass the
+   *  callback check.
+   * @example
+   *
+   * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [1, 3, 5]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.reject(food, 'organic');
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.reject(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   */
+  function reject(collection, callback, thisArg) {
+    callback = createCallback(callback, thisArg);
+    return filter(collection, function(value, index, collection) {
+      return !callback(value, index, collection);
+    });
+  }
+
+  /**
+   * Creates an array of shuffled `array` values, using a version of the
+   * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to shuffle.
+   * @returns {Array} Returns a new shuffled collection.
+   * @example
+   *
+   * _.shuffle([1, 2, 3, 4, 5, 6]);
+   * // => [4, 1, 6, 3, 5, 2]
+   */
+  function shuffle(collection) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      var rand = floor(nativeRandom() * (++index + 1));
+      result[index] = result[rand];
+      result[rand] = value;
+    });
+    return result;
+  }
+
+  /**
+   * Gets the size of the `collection` by returning `collection.length` for arrays
+   * and array-like objects or the number of own enumerable properties for objects.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to inspect.
+   * @returns {Number} Returns `collection.length` or number of own enumerable properties.
+   * @example
+   *
+   * _.size([1, 2]);
+   * // => 2
+   *
+   * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => 3
+   *
+   * _.size('curly');
+   * // => 5
+   */
+  function size(collection) {
+    var length = collection ? collection.length : 0;
+    return typeof length == 'number' ? length : keys(collection).length;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **any** element of a
+   * `collection`. The function returns as soon as it finds passing value, and
+   * does not iterate over the entire `collection`. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias any
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if any element passes the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.some([null, 0, 'yes', false], Boolean);
+   * // => true
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.some(food, 'organic');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.some(food, { 'type': 'meat' });
+   * // => false
+   */
+  function some(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if ((result = callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return !(result = callback(value, index, collection));
+      });
+    }
+    return !!result;
+  }
+
+  /**
+   * Creates an array of elements, sorted in ascending order by the results of
+   * running each element in the `collection` through the `callback`. This method
+   * performs a stable sort, that is, it will preserve the original sort order of
+   * equal elements. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of sorted elements.
+   * @example
+   *
+   * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+   * // => [3, 1, 2]
+   *
+   * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+   * // => [3, 1, 2]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
+   * // => ['apple', 'banana', 'strawberry']
+   */
+  function sortBy(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    forEach(collection, function(value, key, collection) {
+      result[++index] = {
+        'criteria': callback(value, key, collection),
+        'index': index,
+        'value': value
+      };
+    });
+
+    length = result.length;
+    result.sort(compareAscending);
+    while (length--) {
+      result[length] = result[length].value;
+    }
+    return result;
+  }
+
+  /**
+   * Converts the `collection` to an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to convert.
+   * @returns {Array} Returns the new converted array.
+   * @example
+   *
+   * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+   * // => [2, 3, 4]
+   */
+  function toArray(collection) {
+    if (collection && typeof collection.length == 'number') {
+      return noCharByIndex && isString(collection)
+        ? collection.split('')
+        : slice(collection);
+    }
+    return values(collection);
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * that have the given `properties`. When checking `properties`, this method
+   * performs a deep comparison between values to determine if they are equivalent
+   * to each other.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Object} properties The object of property values to filter by.
+   * @returns {Array} Returns a new array of elements that have the given `properties`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.where(stooges, { 'age': 40 });
+   * // => [{ 'name': 'moe', 'age': 40 }]
+   */
+  var where = filter;
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array with all falsey values of `array` removed. The values
+   * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.compact([0, 1, false, 2, '', 3]);
+   * // => [1, 2, 3]
+   */
+  function compact(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (value) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of `array` elements not present in the other arrays
+   * using strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Array} [array1, array2, ...] Arrays to check.
+   * @returns {Array} Returns a new array of `array` elements not present in the
+   *  other arrays.
+   * @example
+   *
+   * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+   * // => [1, 3, 4]
+   */
+  function difference(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        flattened = concat.apply(arrayRef, arguments),
+        contains = cachedContains(flattened, length),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (!contains(value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the first element of the `array`. If a number `n` is passed, the first
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the first elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias head, take
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the first element(s) of `array`.
+   * @example
+   *
+   * _.first([1, 2, 3]);
+   * // => 1
+   *
+   * _.first([1, 2, 3], 2);
+   * // => [1, 2]
+   *
+   * _.first([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [1, 2]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.first(food, 'organic');
+   * // => [{ 'name': 'banana', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.first(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
+   */
+  function first(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = createCallback(callback, thisArg);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[0];
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+  }
+
+  /**
+   * Flattens a nested array (the nesting can be to any depth). If `shallow` is
+   * truthy, `array` will only be flattened a single level.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @param {Boolean} shallow A flag to indicate only flattening a single level.
+   * @returns {Array} Returns a new flattened array.
+   * @example
+   *
+   * _.flatten([1, [2], [3, [[4]]]]);
+   * // => [1, 2, 3, 4];
+   *
+   * _.flatten([1, [2], [3, [[4]]]], true);
+   * // => [1, 2, 3, [[4]]];
+   */
+  function flatten(array, shallow) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+
+      // recursively flatten arrays (susceptible to call stack limits)
+      if (isArray(value)) {
+        push.apply(result, shallow ? value : flatten(value));
+      } else {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the index at which the first occurrence of `value` is found using
+   * strict equality for comparisons, i.e. `===`. If the `array` is already
+   * sorted, passing `true` for `fromIndex` will run a faster binary search.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
+   *  perform a binary search on a sorted `array`.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 1
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 4
+   *
+   * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+   * // => 2
+   */
+  function indexOf(array, value, fromIndex) {
+    var index = -1,
+        length = array ? array.length : 0;
+
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
+    } else if (fromIndex) {
+      index = sortedIndex(array, value);
+      return array[index] === value ? index : -1;
+    }
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Gets all but the last element of `array`. If a number `n` is passed, the
+   * last `n` elements are excluded from the result. If a `callback` function
+   * is passed, the last elements the `callback` returns truthy for are excluded
+   * from the result. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.initial([1, 2, 3]);
+   * // => [1, 2]
+   *
+   * _.initial([1, 2, 3], 2);
+   * // => [1]
+   *
+   * _.initial([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [1]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.initial(food, 'organic');
+   * // => [{ 'name': 'beet',   'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.initial(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'banana', 'type': 'fruit' }]
+   */
+  function initial(array, callback, thisArg) {
+    if (!array) {
+      return [];
+    }
+    var n = 0,
+        length = array.length;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = length;
+      callback = createCallback(callback, thisArg);
+      while (index-- && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : callback || n;
+    }
+    return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+  }
+
+  /**
+   * Computes the intersection of all the passed-in arrays using strict equality
+   * for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique elements that are present
+   *  in **all** of the arrays.
+   * @example
+   *
+   * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2]
+   */
+  function intersection(array) {
+    var args = arguments,
+        argsLength = args.length,
+        cache = { '0': {} },
+        index = -1,
+        length = array ? array.length : 0,
+        isLarge = length >= 100,
+        result = [],
+        seen = result;
+
+    outer:
+    while (++index < length) {
+      var value = array[index];
+      if (isLarge) {
+        var key = value + '';
+        var inited = hasOwnProperty.call(cache[0], key)
+          ? !(seen = cache[0][key])
+          : (seen = cache[0][key] = []);
+      }
+      if (inited || indexOf(seen, value) < 0) {
+        if (isLarge) {
+          seen.push(value);
+        }
+        var argsIndex = argsLength;
+        while (--argsIndex) {
+          if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {
+            continue outer;
+          }
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the last element of the `array`. If a number `n` is passed, the last
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the last elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the last element(s) of `array`.
+   * @example
+   *
+   * _.last([1, 2, 3]);
+   * // => 3
+   *
+   * _.last([1, 2, 3], 2);
+   * // => [2, 3]
+   *
+   * _.last([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [2, 3]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.last(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.last(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
+   */
+  function last(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = createCallback(callback, thisArg);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[length - 1];
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+  }
+
+  /**
+   * Gets the index at which the last occurrence of `value` is found using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=array.length-1] The index to search from.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 4
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 1
+   */
+  function lastIndexOf(array, value, fromIndex) {
+    var index = array ? array.length : 0;
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+    }
+    while (index--) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Creates an object composed from arrays of `keys` and `values`. Pass either
+   * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
+   * two arrays, one of `keys` and one of corresponding `values`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} keys The array of keys.
+   * @param {Array} [values=[]] The array of values.
+   * @returns {Object} Returns an object composed of the given keys and
+   *  corresponding values.
+   * @example
+   *
+   * _.object(['moe', 'larry'], [30, 40]);
+   * // => { 'moe': 30, 'larry': 40 }
+   */
+  function object(keys, values) {
+    var index = -1,
+        length = keys ? keys.length : 0,
+        result = {};
+
+    while (++index < length) {
+      var key = keys[index];
+      if (values) {
+        result[key] = values[index];
+      } else {
+        result[key[0]] = key[1];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of numbers (positive and/or negative) progressing from
+   * `start` up to but not including `end`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Number} [start=0] The start of the range.
+   * @param {Number} end The end of the range.
+   * @param {Number} [step=1] The value to increment or descrement by.
+   * @returns {Array} Returns a new range array.
+   * @example
+   *
+   * _.range(10);
+   * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+   *
+   * _.range(1, 11);
+   * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+   *
+   * _.range(0, 30, 5);
+   * // => [0, 5, 10, 15, 20, 25]
+   *
+   * _.range(0, -10, -1);
+   * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+   *
+   * _.range(0);
+   * // => []
+   */
+  function range(start, end, step) {
+    start = +start || 0;
+    step = +step || 1;
+
+    if (end == null) {
+      end = start;
+      start = 0;
+    }
+    // use `Array(length)` so V8 will avoid the slower "dictionary" mode
+    // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+    var index = -1,
+        length = nativeMax(0, ceil((end - start) / step)),
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = start;
+      start += step;
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.initial`, this method gets all but the first value of `array`.
+   * If a number `n` is passed, the first `n` values are excluded from the result.
+   * If a `callback` function is passed, the first elements the `callback` returns
+   * truthy for are excluded from the result. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias drop, tail
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.rest([1, 2, 3]);
+   * // => [2, 3]
+   *
+   * _.rest([1, 2, 3], 2);
+   * // => [3]
+   *
+   * _.rest([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [3]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.rest(food, 'organic');
+   * // => [{ 'name': 'beet', 'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.rest(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }]
+   */
+  function rest(array, callback, thisArg) {
+    if (typeof callback != 'number' && callback != null) {
+      var n = 0,
+          index = -1,
+          length = array ? array.length : 0;
+
+      callback = createCallback(callback, thisArg);
+      while (++index < length && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+    }
+    return slice(array, n);
+  }
+
+  /**
+   * Uses a binary search to determine the smallest index at which the `value`
+   * should be inserted into `array` in order to maintain the sort order of the
+   * sorted `array`. If `callback` is passed, it will be executed for `value` and
+   * each element in `array` to compute their sort ranking. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to iterate over.
+   * @param {Mixed} value The value to evaluate.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Number} Returns the index at which the value should be inserted
+   *  into `array`.
+   * @example
+   *
+   * _.sortedIndex([20, 30, 50], 40);
+   * // => 2
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+   * // => 2
+   *
+   * var dict = {
+   *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+   * };
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return dict.wordToNumber[word];
+   * });
+   * // => 2
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return this.wordToNumber[word];
+   * }, dict);
+   * // => 2
+   */
+  function sortedIndex(array, value, callback, thisArg) {
+    var low = 0,
+        high = array ? array.length : low;
+
+    // explicitly reference `identity` for better inlining in Firefox
+    callback = callback ? createCallback(callback, thisArg, 1) : identity;
+    value = callback(value);
+
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      callback(array[mid]) < value
+        ? low = mid + 1
+        : high = mid;
+    }
+    return low;
+  }
+
+  /**
+   * Computes the union of the passed-in arrays using strict equality for
+   * comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique values, in order, that are
+   *  present in one or more of the arrays.
+   * @example
+   *
+   * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2, 3, 101, 10]
+   */
+  function union() {
+    return uniq(concat.apply(arrayRef, arguments));
+  }
+
+  /**
+   * Creates a duplicate-value-free version of the `array` using strict equality
+   * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
+   * for `isSorted` will run a faster algorithm. If `callback` is passed, each
+   * element of `array` is passed through a callback` before uniqueness is computed.
+   * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias unique
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a duplicate-value-free array.
+   * @example
+   *
+   * _.uniq([1, 2, 1, 3, 1]);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 1, 2, 2, 3], true);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
+   * // => [1, 2, 3]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+   * // => [{ 'x': 1 }, { 'x': 2 }]
+   */
+  function uniq(array, isSorted, callback, thisArg) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [],
+        seen = result;
+
+    // juggle arguments
+    if (typeof isSorted == 'function') {
+      thisArg = callback;
+      callback = isSorted;
+      isSorted = false;
+    }
+    // init value cache for large arrays
+    var isLarge = !isSorted && length >= 75;
+    if (isLarge) {
+      var cache = {};
+    }
+    if (callback) {
+      seen = [];
+      callback = createCallback(callback, thisArg);
+    }
+    while (++index < length) {
+      var value = array[index],
+          computed = callback ? callback(value, index, array) : value;
+
+      if (isLarge) {
+        var key = computed + '';
+        var inited = hasOwnProperty.call(cache, key)
+          ? !(seen = cache[key])
+          : (seen = cache[key] = []);
+      }
+      if (isSorted
+            ? !index || seen[seen.length - 1] !== computed
+            : inited || indexOf(seen, computed) < 0
+          ) {
+        if (callback || isLarge) {
+          seen.push(computed);
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array with all occurrences of the passed values removed using
+   * strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to filter.
+   * @param {Mixed} [value1, value2, ...] Values to remove.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+   * // => [2, 3, 4]
+   */
+  function without(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        contains = cachedContains(arguments, 1),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (!contains(value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Groups the elements of each array at their corresponding indexes. Useful for
+   * separate data sources that are coordinated through matching array indexes.
+   * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
+   * in a similar fashion.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of grouped elements.
+   * @example
+   *
+   * _.zip(['moe', 'larry'], [30, 40], [true, false]);
+   * // => [['moe', 30, true], ['larry', 40, false]]
+   */
+  function zip(array) {
+    var index = -1,
+        length = array ? max(pluck(arguments, 'length')) : 0,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = pluck(arguments, index);
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function that is restricted to executing `func` only after it is
+   * called `n` times. The `func` is executed with the `this` binding of the
+   * created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Number} n The number of times the function must be called before
+   * it is executed.
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var renderNotes = _.after(notes.length, render);
+   * _.forEach(notes, function(note) {
+   *   note.asyncSave({ 'success': renderNotes });
+   * });
+   * // `renderNotes` is run once, after all notes have saved
+   */
+  function after(n, func) {
+    if (n < 1) {
+      return func();
+    }
+    return function() {
+      if (--n < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this`
+   * binding of `thisArg` and prepends any additional `bind` arguments to those
+   * passed to the bound function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to bind.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var func = function(greeting) {
+   *   return greeting + ' ' + this.name;
+   * };
+   *
+   * func = _.bind(func, { 'name': 'moe' }, 'hi');
+   * func();
+   * // => 'hi moe'
+   */
+  function bind(func, thisArg) {
+    // use `Function#bind` if it exists and is fast
+    // (in V8 `Function#bind` is slower except when partially applied)
+    return isBindFast || (nativeBind && arguments.length > 2)
+      ? nativeBind.call.apply(nativeBind, arguments)
+      : createBound(func, thisArg, slice(arguments, 2));
+  }
+
+  /**
+   * Binds methods on `object` to `object`, overwriting the existing method.
+   * Method names may be specified as individual arguments or as arrays of method
+   * names. If no method names are provided, all the function properties of `object`
+   * will be bound.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object to bind and assign the bound methods to.
+   * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * var view = {
+   *  'label': 'docs',
+   *  'onClick': function() { alert('clicked ' + this.label); }
+   * };
+   *
+   * _.bindAll(view);
+   * jQuery('#docs').on('click', view.onClick);
+   * // => alerts 'clicked docs', when the button is clicked
+   */
+  function bindAll(object) {
+    var funcs = concat.apply(arrayRef, arguments),
+        index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
+        length = funcs.length;
+
+    while (++index < length) {
+      var key = funcs[index];
+      object[key] = bind(object[key], object);
+    }
+    return object;
+  }
+
+  /**
+   * Creates a function that, when called, invokes the method at `object[key]`
+   * and prepends any additional `bindKey` arguments to those passed to the bound
+   * function. This method differs from `_.bind` by allowing bound functions to
+   * reference methods that will be redefined or don't yet exist.
+   * See http://michaux.ca/articles/lazy-function-definition-pattern.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object the method belongs to.
+   * @param {String} key The key of the method.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var object = {
+   *   'name': 'moe',
+   *   'greet': function(greeting) {
+   *     return greeting + ' ' + this.name;
+   *   }
+   * };
+   *
+   * var func = _.bindKey(object, 'greet', 'hi');
+   * func();
+   * // => 'hi moe'
+   *
+   * object.greet = function(greeting) {
+   *   return greeting + ', ' + this.name + '!';
+   * };
+   *
+   * func();
+   * // => 'hi, moe!'
+   */
+  function bindKey(object, key) {
+    return createBound(object, key, slice(arguments, 2));
+  }
+
+  /**
+   * Creates a function that is the composition of the passed functions,
+   * where each function consumes the return value of the function that follows.
+   * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+   * Each function is executed with the `this` binding of the composed function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} [func1, func2, ...] Functions to compose.
+   * @returns {Function} Returns the new composed function.
+   * @example
+   *
+   * var greet = function(name) { return 'hi ' + name; };
+   * var exclaim = function(statement) { return statement + '!'; };
+   * var welcome = _.compose(exclaim, greet);
+   * welcome('moe');
+   * // => 'hi moe!'
+   */
+  function compose() {
+    var funcs = arguments;
+    return function() {
+      var args = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        args = [funcs[length].apply(this, args)];
+      }
+      return args[0];
+    };
+  }
+
+  /**
+   * Creates a function that will delay the execution of `func` until after
+   * `wait` milliseconds have elapsed since the last time it was invoked. Pass
+   * `true` for `immediate` to cause debounce to invoke `func` on the leading,
+   * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
+   * the debounced function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to debounce.
+   * @param {Number} wait The number of milliseconds to delay.
+   * @param {Boolean} immediate A flag to indicate execution is on the leading
+   *  edge of the timeout.
+   * @returns {Function} Returns the new debounced function.
+   * @example
+   *
+   * var lazyLayout = _.debounce(calculateLayout, 300);
+   * jQuery(window).on('resize', lazyLayout);
+   */
+  function debounce(func, wait, immediate) {
+    var args,
+        result,
+        thisArg,
+        timeoutId;
+
+    function delayed() {
+      timeoutId = null;
+      if (!immediate) {
+        result = func.apply(thisArg, args);
+      }
+    }
+    return function() {
+      var isImmediate = immediate && !timeoutId;
+      args = arguments;
+      thisArg = this;
+
+      clearTimeout(timeoutId);
+      timeoutId = setTimeout(delayed, wait);
+
+      if (isImmediate) {
+        result = func.apply(thisArg, args);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Executes the `func` function after `wait` milliseconds. Additional arguments
+   * will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to delay.
+   * @param {Number} wait The number of milliseconds to delay execution.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * var log = _.bind(console.log, console);
+   * _.delay(log, 1000, 'logged later');
+   * // => 'logged later' (Appears after one second.)
+   */
+  function delay(func, wait) {
+    var args = slice(arguments, 2);
+    return setTimeout(function() { func.apply(undefined, args); }, wait);
+  }
+
+  /**
+   * Defers executing the `func` function until the current call stack has cleared.
+   * Additional arguments will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to defer.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * _.defer(function() { alert('deferred'); });
+   * // returns from the function before `alert` is called
+   */
+  function defer(func) {
+    var args = slice(arguments, 1);
+    return setTimeout(function() { func.apply(undefined, args); }, 1);
+  }
+  // use `setImmediate` if it's available in Node.js
+  if (isV8 && freeModule && typeof setImmediate == 'function') {
+    defer = bind(setImmediate, window);
+  }
+
+  /**
+   * Creates a function that memoizes the result of `func`. If `resolver` is
+   * passed, it will be used to determine the cache key for storing the result
+   * based on the arguments passed to the memoized function. By default, the first
+   * argument passed to the memoized function is used as the cache key. The `func`
+   * is executed with the `this` binding of the memoized function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to have its output memoized.
+   * @param {Function} [resolver] A function used to resolve the cache key.
+   * @returns {Function} Returns the new memoizing function.
+   * @example
+   *
+   * var fibonacci = _.memoize(function(n) {
+   *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+   * });
+   */
+  function memoize(func, resolver) {
+    var cache = {};
+    return function() {
+      var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
+      return hasOwnProperty.call(cache, key)
+        ? cache[key]
+        : (cache[key] = func.apply(this, arguments));
+    };
+  }
+
+  /**
+   * Creates a function that is restricted to execute `func` once. Repeat calls to
+   * the function will return the value of the first call. The `func` is executed
+   * with the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var initialize = _.once(createApplication);
+   * initialize();
+   * initialize();
+   * // `initialize` executes `createApplication` once
+   */
+  function once(func) {
+    var ran,
+        result;
+
+    return function() {
+      if (ran) {
+        return result;
+      }
+      ran = true;
+      result = func.apply(this, arguments);
+
+      // clear the `func` variable so the function may be garbage collected
+      func = null;
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with any additional
+   * `partial` arguments prepended to those passed to the new function. This
+   * method is similar to `_.bind`, except it does **not** alter the `this` binding.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var greet = function(greeting, name) { return greeting + ' ' + name; };
+   * var hi = _.partial(greet, 'hi');
+   * hi('moe');
+   * // => 'hi moe'
+   */
+  function partial(func) {
+    return createBound(func, slice(arguments, 1));
+  }
+
+  /**
+   * This method is similar to `_.partial`, except that `partial` arguments are
+   * appended to those passed to the new function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var defaultsDeep = _.partialRight(_.merge, _.defaults);
+   *
+   * var options = {
+   *   'variable': 'data',
+   *   'imports': { 'jq': $ }
+   * };
+   *
+   * defaultsDeep(options, _.templateSettings);
+   *
+   * options.variable
+   * // => 'data'
+   *
+   * options.imports
+   * // => { '_': _, 'jq': $ }
+   */
+  function partialRight(func) {
+    return createBound(func, slice(arguments, 1), null, indicatorObject);
+  }
+
+  /**
+   * Creates a function that, when executed, will only call the `func`
+   * function at most once per every `wait` milliseconds. If the throttled
+   * function is invoked more than once during the `wait` timeout, `func` will
+   * also be called on the trailing edge of the timeout. Subsequent calls to the
+   * throttled function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to throttle.
+   * @param {Number} wait The number of milliseconds to throttle executions to.
+   * @returns {Function} Returns the new throttled function.
+   * @example
+   *
+   * var throttled = _.throttle(updatePosition, 100);
+   * jQuery(window).on('scroll', throttled);
+   */
+  function throttle(func, wait) {
+    var args,
+        result,
+        thisArg,
+        timeoutId,
+        lastCalled = 0;
+
+    function trailingCall() {
+      lastCalled = new Date;
+      timeoutId = null;
+      result = func.apply(thisArg, args);
+    }
+    return function() {
+      var now = new Date,
+          remaining = wait - (now - lastCalled);
+
+      args = arguments;
+      thisArg = this;
+
+      if (remaining <= 0) {
+        clearTimeout(timeoutId);
+        timeoutId = null;
+        lastCalled = now;
+        result = func.apply(thisArg, args);
+      }
+      else if (!timeoutId) {
+        timeoutId = setTimeout(trailingCall, remaining);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that passes `value` to the `wrapper` function as its
+   * first argument. Additional arguments passed to the function are appended
+   * to those passed to the `wrapper` function. The `wrapper` is executed with
+   * the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Mixed} value The value to wrap.
+   * @param {Function} wrapper The wrapper function.
+   * @returns {Function} Returns the new function.
+   * @example
+   *
+   * var hello = function(name) { return 'hello ' + name; };
+   * hello = _.wrap(hello, function(func) {
+   *   return 'before, ' + func('moe') + ', after';
+   * });
+   * hello();
+   * // => 'before, hello moe, after'
+   */
+  function wrap(value, wrapper) {
+    return function() {
+      var args = [value];
+      push.apply(args, arguments);
+      return wrapper.apply(this, args);
+    };
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+   * corresponding HTML entities.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to escape.
+   * @returns {String} Returns the escaped string.
+   * @example
+   *
+   * _.escape('Moe, Larry & Curly');
+   * // => 'Moe, Larry &amp; Curly'
+   */
+  function escape(string) {
+    return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
+  }
+
+  /**
+   * This function returns the first argument passed to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Mixed} value Any value.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * var moe = { 'name': 'moe' };
+   * moe === _.identity(moe);
+   * // => true
+   */
+  function identity(value) {
+    return value;
+  }
+
+  /**
+   * Adds functions properties of `object` to the `lodash` function and chainable
+   * wrapper.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object of function properties to add to `lodash`.
+   * @example
+   *
+   * _.mixin({
+   *   'capitalize': function(string) {
+   *     return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+   *   }
+   * });
+   *
+   * _.capitalize('moe');
+   * // => 'Moe'
+   *
+   * _('moe').capitalize();
+   * // => 'Moe'
+   */
+  function mixin(object) {
+    forEach(functions(object), function(methodName) {
+      var func = lodash[methodName] = object[methodName];
+
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        return new lodash(func.apply(lodash, args));
+      };
+    });
+  }
+
+  /**
+   * Reverts the '_' variable to its previous value and returns a reference to
+   * the `lodash` function.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @returns {Function} Returns the `lodash` function.
+   * @example
+   *
+   * var lodash = _.noConflict();
+   */
+  function noConflict() {
+    window._ = oldDash;
+    return this;
+  }
+
+  /**
+   * Produces a random number between `min` and `max` (inclusive). If only one
+   * argument is passed, a number between `0` and the given number will be returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} [min=0] The minimum possible value.
+   * @param {Number} [max=1] The maximum possible value.
+   * @returns {Number} Returns a random number.
+   * @example
+   *
+   * _.random(0, 5);
+   * // => a number between 0 and 5
+   *
+   * _.random(5);
+   * // => also a number between 0 and 5
+   */
+  function random(min, max) {
+    if (min == null && max == null) {
+      max = 1;
+    }
+    min = +min || 0;
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + floor(nativeRandom() * ((+max || 0) - min + 1));
+  }
+
+  /**
+   * Resolves the value of `property` on `object`. If `property` is a function,
+   * it will be invoked and its result returned, else the property value is
+   * returned. If `object` is falsey, then `null` is returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object to inspect.
+   * @param {String} property The property to get the value of.
+   * @returns {Mixed} Returns the resolved value.
+   * @example
+   *
+   * var object = {
+   *   'cheese': 'crumpets',
+   *   'stuff': function() {
+   *     return 'nonsense';
+   *   }
+   * };
+   *
+   * _.result(object, 'cheese');
+   * // => 'crumpets'
+   *
+   * _.result(object, 'stuff');
+   * // => 'nonsense'
+   */
+  function result(object, property) {
+    var value = object ? object[property] : undefined;
+    return isFunction(value) ? object[property]() : value;
+  }
+
+  /**
+   * A micro-templating method that handles arbitrary delimiters, preserves
+   * whitespace, and correctly escapes quotes within interpolated code.
+   *
+   * Note: In the development build, `_.template` utilizes sourceURLs for easier
+   * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+   *
+   * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
+   * build and using precompiled templates, or loading Lo-Dash in a sandbox.
+   *
+   * For more information on precompiling templates see:
+   * http://lodash.com/#custom-builds
+   *
+   * For more information on Chrome extension sandboxes see:
+   * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} text The template text.
+   * @param {Obect} data The data object used to populate the text.
+   * @param {Object} options The options object.
+   *  escape - The "escape" delimiter regexp.
+   *  evaluate - The "evaluate" delimiter regexp.
+   *  interpolate - The "interpolate" delimiter regexp.
+   *  sourceURL - The sourceURL of the template's compiled source.
+   *  variable - The data object variable name.
+   *
+   * @returns {Function|String} Returns a compiled function when no `data` object
+   *  is given, else it returns the interpolated text.
+   * @example
+   *
+   * // using a compiled template
+   * var compiled = _.template('hello <%= name %>');
+   * compiled({ 'name': 'moe' });
+   * // => 'hello moe'
+   *
+   * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
+   * _.template(list, { 'people': ['moe', 'larry'] });
+   * // => '<li>moe</li><li>larry</li>'
+   *
+   * // using the "escape" delimiter to escape HTML in data property values
+   * _.template('<b><%- value %></b>', { 'value': '<script>' });
+   * // => '<b>&lt;script&gt;</b>'
+   *
+   * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+   * _.template('hello ${ name }', { 'name': 'curly' });
+   * // => 'hello curly'
+   *
+   * // using the internal `print` function in "evaluate" delimiters
+   * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
+   * // => 'hello stooge!'
+   *
+   * // using custom template delimiters
+   * _.templateSettings = {
+   *   'interpolate': /{{([\s\S]+?)}}/g
+   * };
+   *
+   * _.template('hello {{ name }}!', { 'name': 'mustache' });
+   * // => 'hello mustache!'
+   *
+   * // using the `sourceURL` option to specify a custom sourceURL for the template
+   * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+   * compiled(data);
+   * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+   *
+   * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+   * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+   * compiled.source;
+   * // => function(data) {
+   *   var __t, __p = '', __e = _.escape;
+   *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+   *   return __p;
+   * }
+   *
+   * // using the `source` property to inline compiled templates for meaningful
+   * // line numbers in error messages and a stack trace
+   * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+   *   var JST = {\
+   *     "main": ' + _.template(mainText).source + '\
+   *   };\
+   * ');
+   */
+  function template(text, data, options) {
+    // based on John Resig's `tmpl` implementation
+    // http://ejohn.org/blog/javascript-micro-templating/
+    // and Laura Doktorova's doT.js
+    // https://github.com/olado/doT
+    var settings = lodash.templateSettings;
+    text || (text = '');
+
+    // avoid missing dependencies when `iteratorTemplate` is not defined
+    options = defaults({}, options, settings);
+
+    var imports = defaults({}, options.imports, settings.imports),
+        importsKeys = keys(imports),
+        importsValues = values(imports);
+
+    var isEvaluating,
+        index = 0,
+        interpolate = options.interpolate || reNoMatch,
+        source = "__p += '";
+
+    // compile regexp to match each delimiter
+    var reDelimiters = RegExp(
+      (options.escape || reNoMatch).source + '|' +
+      interpolate.source + '|' +
+      (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+      (options.evaluate || reNoMatch).source + '|$'
+    , 'g');
+
+    text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+      interpolateValue || (interpolateValue = esTemplateValue);
+
+      // escape characters that cannot be included in string literals
+      source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+      // replace delimiters with snippets
+      if (escapeValue) {
+        source += "' +\n__e(" + escapeValue + ") +\n'";
+      }
+      if (evaluateValue) {
+        isEvaluating = true;
+        source += "';\n" + evaluateValue + ";\n__p += '";
+      }
+      if (interpolateValue) {
+        source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+      }
+      index = offset + match.length;
+
+      // the JS engine embedded in Adobe products requires returning the `match`
+      // string in order to produce the correct `offset` value
+      return match;
+    });
+
+    source += "';\n";
+
+    // if `variable` is not specified and the template contains "evaluate"
+    // delimiters, wrap a with-statement around the generated code to add the
+    // data object to the top of the scope chain
+    var variable = options.variable,
+        hasVariable = variable;
+
+    if (!hasVariable) {
+      variable = 'obj';
+      source = 'with (' + variable + ') {\n' + source + '\n}\n';
+    }
+    // cleanup code by stripping empty strings
+    source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+      .replace(reEmptyStringMiddle, '$1')
+      .replace(reEmptyStringTrailing, '$1;');
+
+    // frame code as the function body
+    source = 'function(' + variable + ') {\n' +
+      (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+      "var __t, __p = '', __e = _.escape" +
+      (isEvaluating
+        ? ', __j = Array.prototype.join;\n' +
+          "function print() { __p += __j.call(arguments, '') }\n"
+        : ';\n'
+      ) +
+      source +
+      'return __p\n}';
+
+    // Use a sourceURL for easier debugging and wrap in a multi-line comment to
+    // avoid issues with Narwhal, IE conditional compilation, and the JS engine
+    // embedded in Adobe products.
+    // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+    var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
+
+    try {
+      var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
+    } catch(e) {
+      e.source = source;
+      throw e;
+    }
+    if (data) {
+      return result(data);
+    }
+    // provide the compiled function's source via its `toString` method, in
+    // supported environments, or the `source` property as a convenience for
+    // inlining compiled templates during the build process
+    result.source = source;
+    return result;
+  }
+
+  /**
+   * Executes the `callback` function `n` times, returning an array of the results
+   * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
+   * with one argument; (index).
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} n The number of times to execute the callback.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+   * // => [3, 6, 4]
+   *
+   * _.times(3, function(n) { mage.castSpell(n); });
+   * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+   *
+   * _.times(3, function(n) { this.cast(n); }, mage);
+   * // => also calls `mage.castSpell(n)` three times
+   */
+  function times(n, callback, thisArg) {
+    n = +n || 0;
+    var index = -1,
+        result = Array(n);
+
+    while (++index < n) {
+      result[index] = callback.call(thisArg, index);
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.escape`, this method converts the HTML entities
+   * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+   * corresponding characters.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to unescape.
+   * @returns {String} Returns the unescaped string.
+   * @example
+   *
+   * _.unescape('Moe, Larry &amp; Curly');
+   * // => 'Moe, Larry & Curly'
+   */
+  function unescape(string) {
+    return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
+  }
+
+  /**
+   * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} [prefix] The value to prefix the ID with.
+   * @returns {String} Returns the unique ID.
+   * @example
+   *
+   * _.uniqueId('contact_');
+   * // => 'contact_104'
+   *
+   * _.uniqueId();
+   * // => '105'
+   */
+  function uniqueId(prefix) {
+    var id = ++idCounter;
+    return (prefix == null ? '' : prefix + '') + id;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Invokes `interceptor` with the `value` as the first argument, and then
+   * returns `value`. The purpose of this method is to "tap into" a method chain,
+   * in order to perform operations on intermediate results within the chain.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {Mixed} value The value to pass to `interceptor`.
+   * @param {Function} interceptor The function to invoke.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * _([1, 2, 3, 4])
+   *  .filter(function(num) { return num % 2 == 0; })
+   *  .tap(alert)
+   *  .map(function(num) { return num * num; })
+   *  .value();
+   * // => // [2, 4] (alerted)
+   * // => [4, 16]
+   */
+  function tap(value, interceptor) {
+    interceptor(value);
+    return value;
+  }
+
+  /**
+   * Produces the `toString` result of the wrapped value.
+   *
+   * @name toString
+   * @memberOf _
+   * @category Chaining
+   * @returns {String} Returns the string result.
+   * @example
+   *
+   * _([1, 2, 3]).toString();
+   * // => '1,2,3'
+   */
+  function wrapperToString() {
+    return this.__wrapped__ + '';
+  }
+
+  /**
+   * Extracts the wrapped value.
+   *
+   * @name valueOf
+   * @memberOf _
+   * @alias value
+   * @category Chaining
+   * @returns {Mixed} Returns the wrapped value.
+   * @example
+   *
+   * _([1, 2, 3]).valueOf();
+   * // => [1, 2, 3]
+   */
+  function wrapperValueOf() {
+    return this.__wrapped__;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return wrapped values when chaining
+  lodash.after = after;
+  lodash.assign = assign;
+  lodash.at = at;
+  lodash.bind = bind;
+  lodash.bindAll = bindAll;
+  lodash.bindKey = bindKey;
+  lodash.compact = compact;
+  lodash.compose = compose;
+  lodash.countBy = countBy;
+  lodash.debounce = debounce;
+  lodash.defaults = defaults;
+  lodash.defer = defer;
+  lodash.delay = delay;
+  lodash.difference = difference;
+  lodash.filter = filter;
+  lodash.flatten = flatten;
+  lodash.forEach = forEach;
+  lodash.forIn = forIn;
+  lodash.forOwn = forOwn;
+  lodash.functions = functions;
+  lodash.groupBy = groupBy;
+  lodash.initial = initial;
+  lodash.intersection = intersection;
+  lodash.invert = invert;
+  lodash.invoke = invoke;
+  lodash.keys = keys;
+  lodash.map = map;
+  lodash.max = max;
+  lodash.memoize = memoize;
+  lodash.merge = merge;
+  lodash.min = min;
+  lodash.object = object;
+  lodash.omit = omit;
+  lodash.once = once;
+  lodash.pairs = pairs;
+  lodash.partial = partial;
+  lodash.partialRight = partialRight;
+  lodash.pick = pick;
+  lodash.pluck = pluck;
+  lodash.range = range;
+  lodash.reject = reject;
+  lodash.rest = rest;
+  lodash.shuffle = shuffle;
+  lodash.sortBy = sortBy;
+  lodash.tap = tap;
+  lodash.throttle = throttle;
+  lodash.times = times;
+  lodash.toArray = toArray;
+  lodash.union = union;
+  lodash.uniq = uniq;
+  lodash.values = values;
+  lodash.where = where;
+  lodash.without = without;
+  lodash.wrap = wrap;
+  lodash.zip = zip;
+
+  // add aliases
+  lodash.collect = map;
+  lodash.drop = rest;
+  lodash.each = forEach;
+  lodash.extend = assign;
+  lodash.methods = functions;
+  lodash.select = filter;
+  lodash.tail = rest;
+  lodash.unique = uniq;
+
+  // add functions to `lodash.prototype`
+  mixin(lodash);
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return unwrapped values when chaining
+  lodash.clone = clone;
+  lodash.cloneDeep = cloneDeep;
+  lodash.contains = contains;
+  lodash.escape = escape;
+  lodash.every = every;
+  lodash.find = find;
+  lodash.has = has;
+  lodash.identity = identity;
+  lodash.indexOf = indexOf;
+  lodash.isArguments = isArguments;
+  lodash.isArray = isArray;
+  lodash.isBoolean = isBoolean;
+  lodash.isDate = isDate;
+  lodash.isElement = isElement;
+  lodash.isEmpty = isEmpty;
+  lodash.isEqual = isEqual;
+  lodash.isFinite = isFinite;
+  lodash.isFunction = isFunction;
+  lodash.isNaN = isNaN;
+  lodash.isNull = isNull;
+  lodash.isNumber = isNumber;
+  lodash.isObject = isObject;
+  lodash.isPlainObject = isPlainObject;
+  lodash.isRegExp = isRegExp;
+  lodash.isString = isString;
+  lodash.isUndefined = isUndefined;
+  lodash.lastIndexOf = lastIndexOf;
+  lodash.mixin = mixin;
+  lodash.noConflict = noConflict;
+  lodash.random = random;
+  lodash.reduce = reduce;
+  lodash.reduceRight = reduceRight;
+  lodash.result = result;
+  lodash.size = size;
+  lodash.some = some;
+  lodash.sortedIndex = sortedIndex;
+  lodash.template = template;
+  lodash.unescape = unescape;
+  lodash.uniqueId = uniqueId;
+
+  // add aliases
+  lodash.all = every;
+  lodash.any = some;
+  lodash.detect = find;
+  lodash.foldl = reduce;
+  lodash.foldr = reduceRight;
+  lodash.include = contains;
+  lodash.inject = reduce;
+
+  forOwn(lodash, function(func, methodName) {
+    if (!lodash.prototype[methodName]) {
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        return func.apply(lodash, args);
+      };
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions capable of returning wrapped and unwrapped values when chaining
+  lodash.first = first;
+  lodash.last = last;
+
+  // add aliases
+  lodash.take = first;
+  lodash.head = first;
+
+  forOwn(lodash, function(func, methodName) {
+    if (!lodash.prototype[methodName]) {
+      lodash.prototype[methodName]= function(callback, thisArg) {
+        var result = func(this.__wrapped__, callback, thisArg);
+        return callback == null || (thisArg && typeof callback != 'function')
+          ? result
+          : new lodash(result);
+      };
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The semantic version number.
+   *
+   * @static
+   * @memberOf _
+   * @type String
+   */
+  lodash.VERSION = '1.0.1';
+
+  // add "Chaining" functions to the wrapper
+  lodash.prototype.toString = wrapperToString;
+  lodash.prototype.value = wrapperValueOf;
+  lodash.prototype.valueOf = wrapperValueOf;
+
+  // add `Array` functions that return unwrapped values
+  each(['join', 'pop', 'shift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      return func.apply(this.__wrapped__, arguments);
+    };
+  });
+
+  // add `Array` functions that return the wrapped value
+  each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      func.apply(this.__wrapped__, arguments);
+      return this;
+    };
+  });
+
+  // add `Array` functions that return new wrapped values
+  each(['concat', 'slice', 'splice'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      return new lodash(func.apply(this.__wrapped__, arguments));
+    };
+  });
+
+  // avoid array-like object bugs with `Array#shift` and `Array#splice`
+  // in Firefox < 10 and IE < 9
+  if (hasObjectSpliceBug) {
+    each(['pop', 'shift', 'splice'], function(methodName) {
+      var func = arrayRef[methodName],
+          isSplice = methodName == 'splice';
+
+      lodash.prototype[methodName] = function() {
+        var value = this.__wrapped__,
+            result = func.apply(value, arguments);
+
+        if (value.length === 0) {
+          delete value[0];
+        }
+        return isSplice ? new lodash(result) : result;
+      };
+    });
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Lo-Dash
+  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash was injected by a third-party script and not intended to be
+    // loaded as a module. The global assignment can be reverted in the Lo-Dash
+    // module via its `noConflict()` method.
+    window._ = lodash;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return lodash;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports) {
+    // in Node.js or RingoJS v0.8.0+
+    if (freeModule) {
+      (freeModule.exports = lodash)._ = lodash;
+    }
+    // in Narwhal or RingoJS v0.7.0-
+    else {
+      freeExports._ = lodash;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    window._ = lodash;
+  }
+}(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.min.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.min.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.min.js	(revision 533)
@@ -0,0 +1,42 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 (Custom Build) lodash.com/license
+ * Build: `lodash -o ./dist/lodash.compat.js`
+ * Underscore.js 1.4.4 underscorejs.org/LICENSE
+ */
+;(function(n,t){function r(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof r?(this.__wrapped__=n,void 0):new r(n)}function e(n,t,r){t||(t=0);var e=n.length,u=e-t>=(r||at);if(u){var o={};for(r=t-1;++r<e;){var i=n[r]+"";(St.call(o,i)?o[i]:o[i]=[]).push(n[r])}}return function(r){if(u){var e=r+"";return St.call(o,e)&&-1<z(o[e],r)}return-1<z(n,r,t)}}function u(n){return n.charCodeAt(0)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
+}return r<e?-1:1}function i(n,t,r,e){function u(){var a=arguments,c=i?this:t;return o||(n=t[f]),r.length&&(a=a.length?(a=v(a),e?a.concat(r):r.concat(a)):r),this instanceof u?(s.prototype=n.prototype,c=new s,s.prototype=W,a=n.apply(c,a),x(a)?a:c):n.apply(c,a)}var o=w(n),i=!r,f=t;return i&&(r=t),o||(t=n),u}function f(n,t,r){if(n==W)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=vr(n);return function(t){for(var r=u.length,e=X;r--&&(e=j(t[u[r]],n[u[r]],ft)););return e
+}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function a(){for(var n,t={e:tt,f:rt,g:Jt,i:Wt,j:Zt,k:jt,b:"l(n)",c:"",h:"",l:"",m:Q},r=0;n=arguments[r];r++)for(var e in n)t[e]=n[e];if(n=t.a,t.d=/^[^,]+/.exec(n)[0],r="var j,n="+t.d+",u=n;if(!n)return u;"+t.l+";",t.b?(r+="var o=n.length;j=-1;if("+t.b+"){",t.j&&(r+="if(m(n)){n=n.split('')}"),r+="while(++j<o){"+t.h+"}}else{"):t.i&&(r+="var o=n.length;j=-1;if(o&&k(n)){while(++j<o){j+='';"+t.h+"}}else{"),t.f&&(r+="var v=typeof n=='function';"),t.g&&t.m?(r+="var s=-1,t=r[typeof n]?p(n):[],o=t.length;while(++s<o){j=t[s];",t.f&&(r+="if(!(v&&j=='prototype')){"),r+=t.h+"",t.f&&(r+="}")):(r+="for(j in n){",(t.f||t.m)&&(r+="if(",t.f&&(r+="!(v&&j=='prototype')"),t.f&&t.m&&(r+="&&"),t.m&&(r+="i.call(n,j)"),r+="){"),r+=t.h+";",(t.f||t.m)&&(r+="}")),r+="}",t.e)for(r+="var g=n.constructor;",e=0;7>e;e++)r+="j='"+t.k[e]+"';if(","constructor"==t.k[e]&&(r+="!(g&&g.prototype===n)&&"),r+="i.call(n,j)){"+t.h+"}";
+return(t.b||t.i)&&(r+="}"),r+=t.c+";return u",Function("f,i,k,l,m,r,p","return function("+n+"){"+r+"}")(f,St,y,sr,A,ur,Ft)}function c(n){return"\\"+or[n]}function l(n){return gr[n]}function p(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function s(){}function v(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function g(n){return yr[n]}function y(n){return kt.call(n)==Bt}function h(n){var t=X;if(!n||typeof n!="object"||y(n))return t;
+var r=n.constructor;return!w(r)&&(!nr||!p(n))||r instanceof r?et?(lr(n,function(n,r,e){return t=!St.call(e,r),X}),t===X):(lr(n,function(n,r){t=r}),t===X||St.call(n,t)):t}function m(n){var t=[];return pr(n,function(n,r){t.push(r)}),t}function d(n,r,e,u,o,i){var a=n;if(typeof r=="function"&&(u=e,e=r,r=X),typeof e=="function"){e=typeof u=="undefined"?e:f(e,u,1);var a=e(a),c=typeof a!="undefined";c||(a=n)}if(u=x(a)){var l=kt.call(a);if(!rr[l]||nr&&p(a))return a;var s=sr(a)}if(!u||!r)return u&&!c?s?v(a):hr({},a):a;
+switch(u=er[l],l){case Pt:case zt:return c?a:new u(+a);case Ct:case Ut:return c?a:new u(a);case Lt:return c?a:u(a.source,gt.exec(a))}for(o||(o=[]),i||(i=[]),l=o.length;l--;)if(o[l]==n)return i[l];return c||(a=s?u(a.length):{},s&&(St.call(n,"index")&&(a.index=n.index),St.call(n,"input")&&(a.input=n.input))),o.push(n),i.push(a),(s?$:pr)(c?a:n,function(n,u){a[u]=d(n,r,e,t,o,i)}),a}function _(n){var t=[];return lr(n,function(n,r){w(n)&&t.push(r)}),t.sort()}function b(n){for(var t=-1,r=vr(n),e=r.length,u={};++t<e;){var o=r[t];
+u[n[o]]=o}return u}function j(n,t,r,e,u,o){var i=r===ft;if(r&&!i){r=typeof e=="undefined"?r:f(r,e,2);var a=r(n,t);if(typeof a!="undefined")return!!a}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,l=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=l&&"object"!=l))return X;if(n==W||t==W)return n===t;if(l=kt.call(n),c=kt.call(t),l==Bt&&(l=Kt),c==Bt&&(c=Kt),l!=c)return X;switch(l){case Pt:case zt:return+n==+t;case Ct:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Lt:case Ut:return n==t+""
+}if(c=l==Mt,!c){if(n.__wrapped__||t.__wrapped__)return j(n.__wrapped__||n,t.__wrapped__||t,r,e,u,o);if(l!=Kt||nr&&(p(n)||p(t)))return X;var l=!Xt&&y(n)?Object:n.constructor,s=!Xt&&y(t)?Object:t.constructor;if(l!=s&&(!w(l)||!(l instanceof l&&w(s)&&s instanceof s)))return X}for(u||(u=[]),o||(o=[]),l=u.length;l--;)if(u[l]==n)return o[l]==t;var v=0,a=Q;if(u.push(n),o.push(t),c){if(l=n.length,v=t.length,a=v==n.length,!a&&!i)return a;for(;v--;)if(c=l,s=t[v],i)for(;c--&&!(a=j(n[c],s,r,e,u,o)););else if(!(a=j(n[v],s,r,e,u,o)))break;
+return a}return lr(t,function(t,i,f){return St.call(f,i)?(v++,a=St.call(n,i)&&j(n[i],t,r,e,u,o)):void 0}),a&&!i&&lr(n,function(n,t,r){return St.call(r,t)?a=-1<--v:void 0}),a}function w(n){return typeof n=="function"}function x(n){return n?ur[typeof n]:X}function O(n){return typeof n=="number"||kt.call(n)==Ct}function A(n){return typeof n=="string"||kt.call(n)==Ut}function S(n,t,r){var e=arguments,u=0,o=2;if(!x(n))return n;if(r===ft)var i=e[3],a=e[4],c=e[5];else a=[],c=[],typeof r!="number"&&(o=e.length),3<o&&"function"==typeof e[o-2]?i=f(e[--o-1],e[o--],2):2<o&&"function"==typeof e[o-1]&&(i=e[--o]);
+for(;++u<o;)(sr(e[u])?$:pr)(e[u],function(t,r){var e,u,o=t,f=n[r];if(t&&((u=sr(t))||dr(t))){for(o=a.length;o--;)if(e=a[o]==t){f=c[o];break}e||(f=u?sr(f)?f:[]:dr(f)?f:{},i&&(o=i(f,t),typeof o!="undefined"&&(f=o)),a.push(t),c.push(f),i||(f=S(f,t,ft,i,a,c)))}else i&&(o=i(f,t),typeof o=="undefined"&&(o=t)),typeof o!="undefined"&&(f=o);n[r]=f});return n}function E(n){for(var t=-1,r=vr(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function k(n,t,r){var e=-1,u=n?n.length:0,o=X;return r=(0>r?qt(0,u+r):r)||0,typeof u=="number"?o=-1<(A(n)?n.indexOf(t,r):z(n,t,r)):cr(n,function(n){return++e<r?void 0:!(o=n===t)
+}),o}function I(n,t,r){var e=Q;if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u&&(e=!!t(n[r],r,n)););}else cr(n,function(n,r,u){return e=!!t(n,r,u)});return e}function N(n,t,r){var e=[];if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u;){var o=n[r];t(o,r,n)&&e.push(o)}}else cr(n,function(n,r,u){t(n,r,u)&&e.push(n)});return e}function R(n,t,r){var e;return t=f(t,r),$(n,function(n,r,u){return t(n,r,u)?(e=n,X):void 0}),e}function $(n,t,r){if(t&&typeof r=="undefined"&&sr(n)){r=-1;for(var e=n.length;++r<e&&t(n[r],r,n)!==X;);}else cr(n,t,r);
+return n}function F(n,t,r){var e=-1,u=n?n.length:0,o=Array(typeof u=="number"?u:0);if(t=f(t,r),sr(n))for(;++e<u;)o[e]=t(n[e],e,n);else cr(n,function(n,r,u){o[++e]=t(n,r,u)});return o}function q(n,t,r){var e=-1/0,o=e;if(!t&&sr(n)){r=-1;for(var i=n.length;++r<i;){var a=n[r];a>o&&(o=a)}}else t=!t&&A(n)?u:f(t,r),cr(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function D(n,t,r,e){var u=3>arguments.length;if(t=f(t,e,4),sr(n)){var o=-1,i=n.length;for(u&&(r=n[++o]);++o<i;)r=t(r,n[o],o,n)}else cr(n,function(n,e,o){r=u?(u=X,n):t(r,n,e,o)
+});return r}function T(n,t,r,e){var u=n,o=n?n.length:0,i=3>arguments.length;if(typeof o!="number")var a=vr(n),o=a.length;else Zt&&A(n)&&(u=n.split(""));return t=f(t,e,4),$(n,function(n,e,f){e=a?a[--o]:--o,r=i?(i=X,u[e]):t(r,u[e],e,f)}),r}function B(n,t,r){var e;if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u&&!(e=t(n[r],r,n)););}else cr(n,function(n,r,u){return!(e=t(n,r,u))});return!!e}function M(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=-1;for(t=f(t,r);++o<u&&t(n[o],o,n);)e++
+}else if(e=t,e==W||r)return n[0];return v(n,0,Dt(qt(0,e),u))}}function P(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];sr(o)?Et.apply(u,t?o:P(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;if(typeof r=="number")e=(0>r?qt(0,u+r):r||0)-1;else if(r)return e=K(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function C(n,t,r){if(typeof t!="number"&&t!=W){var e=0,u=-1,o=n?n.length:0;for(t=f(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==W||r?1:qt(0,t);return v(n,e)}function K(n,t,r,e){var u=0,o=n?n.length:u;
+for(r=r?f(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function L(n,t,r,e){var u=-1,o=n?n.length:0,i=[],a=i;typeof t=="function"&&(e=r,r=t,t=X);var c=!t&&75<=o;if(c)var l={};for(r&&(a=[],r=f(r,e));++u<o;){e=n[u];var p=r?r(e,u,n):e;if(c)var s=p+"",s=St.call(l,s)?!(a=l[s]):a=l[s]=[];(t?!u||a[a.length-1]!==p:s||0>z(a,p))&&((r||c)&&a.push(p),i.push(e))}return i}function U(n,t){return Ht||It&&2<arguments.length?It.call.apply(It,arguments):i(n,t,v(arguments,2))}function V(n){var r=v(arguments,1);
+return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){$(_(n),function(t){var e=r[t]=n[t];r.prototype[t]=function(){var n=[this.__wrapped__];return Et.apply(n,arguments),new r(e.apply(r,n))}})}function J(){return this.__wrapped__}var Q=!0,W=null,X=!1,Y=typeof exports=="object"&&exports,Z=typeof module=="object"&&module&&module.exports==Y&&module,nt=typeof global=="object"&&global;nt.global===nt&&(n=nt);var tt,rt,et,ut=[],ot={},it=0,ft=ot,at=30,ct=n._,lt=/&(?:amp|lt|gt|quot|#39);/g,pt=/\b__p\+='';/g,st=/\b(__p\+=)''\+/g,vt=/(__e\(.*?\)|\b__t\))\+'';/g,gt=/\w*$/,yt=RegExp("^"+(ot.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ht=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,mt=/<%=([\s\S]+?)%>/g,dt=/($^)/,_t=/[&<>"']/g,bt=/['\n\r\t\u2028\u2029\\]/g,jt="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),wt=Math.ceil,xt=ut.concat,Ot=Math.floor,At=yt.test(At=Object.getPrototypeOf)&&At,St=ot.hasOwnProperty,Et=ut.push,kt=ot.toString,It=yt.test(It=v.bind)&&It,Nt=yt.test(Nt=Array.isArray)&&Nt,Rt=n.isFinite,$t=n.isNaN,Ft=yt.test(Ft=Object.keys)&&Ft,qt=Math.max,Dt=Math.min,Tt=Math.random,Bt="[object Arguments]",Mt="[object Array]",Pt="[object Boolean]",zt="[object Date]",Ct="[object Number]",Kt="[object Object]",Lt="[object RegExp]",Ut="[object String]",Vt=!!n.attachEvent,Gt=It&&!/\n|true/.test(It+Vt),Ht=It&&!Gt,Jt=Ft&&(Vt||Gt),Qt=(Qt={0:1,length:1},ut.splice.call(Qt,0,1),Qt[0]),Wt=Q;
+(function(){function n(){this.x=1}var t=[];n.prototype={valueOf:1,y:1};for(var r in new n)t.push(r);for(r in arguments)Wt=!r;tt=!/valueOf/.test(t),rt=n.propertyIsEnumerable("prototype"),et="x"!=t[0]})(1);var Xt=arguments.constructor==Object,Yt=!y(arguments),Zt="xx"!="x"[0]+Object("x")[0];try{var nr=kt.call(document)==Kt&&!({toString:0}+"")}catch(tr){}var rr={"[object Function]":X};rr[Bt]=rr[Mt]=rr[Pt]=rr[zt]=rr[Ct]=rr[Kt]=rr[Lt]=rr[Ut]=Q;var er={};er[Mt]=Array,er[Pt]=Boolean,er[zt]=Date,er[Kt]=Object,er[Ct]=Number,er[Lt]=RegExp,er[Ut]=String;
+var ur={"boolean":X,"function":Q,object:Q,number:X,string:X,undefined:X},or={"\\":"\\","'":"'","\n":"n","\r":"r","	":"t","\u2028":"u2028","\u2029":"u2029"};r.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:mt,variable:"",imports:{_:r}};var ir={a:"q,w,h",l:"var a=arguments,b=0,c=typeof h=='number'?2:a.length;while(++b<c){n=a[b];if(n&&r[typeof n]){",h:"if(typeof u[j]=='undefined')u[j]=n[j]",c:"}}"},fr={a:"e,d,x",l:"d=d&&typeof x=='undefined'?d:f(d,x)",b:"typeof o=='number'",h:"if(d(n[j],j,e)===false)return u"},ar={l:"if(!r[typeof n])return u;"+fr.l,b:X},cr=a(fr);
+Yt&&(y=function(n){return n?St.call(n,"callee"):X});var lr=a(fr,ar,{m:X}),pr=a(fr,ar),sr=Nt||function(n){return Xt&&n instanceof Array||kt.call(n)==Mt},vr=Ft?function(n){return x(n)?rt&&typeof n=="function"||Wt&&n.length&&y(n)?m(n):Ft(n):[]}:m,gr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},yr=b(gr),hr=a(ir,{l:ir.l.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=f(a[--c-1],a[c--],2);}else if(c>2&&typeof a[c-1]=='function'){d=a[--c];}"),h:"u[j]=d?d(u[j],n[j]):n[j]"}),mr=a(ir);
+w(/x/)&&(w=function(n){return n instanceof Function||"[object Function]"==kt.call(n)});var dr=At?function(n){if(!n||typeof n!="object")return X;var t=n.valueOf,r=typeof t=="function"&&(r=At(t))&&At(r);return r?n==r||At(n)==r&&!y(n):h(n)}:h,_r=F,br=N;Gt&&Z&&typeof setImmediate=="function"&&(V=U(setImmediate,n)),r.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},r.assign=hr,r.at=function(n){var t=-1,r=xt.apply(ut,v(arguments,1)),e=r.length,u=Array(e);for(Zt&&A(n)&&(n=n.split(""));++t<e;)u[t]=n[r[t]];
+return u},r.bind=U,r.bindAll=function(n){for(var t=xt.apply(ut,arguments),r=1<t.length?0:(t=_(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=U(n[u],n)}return n},r.bindKey=function(n,t){return i(n,t,v(arguments,2))},r.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},r.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},r.countBy=function(n,t,r){var e={};return t=f(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",St.call(e,r)?e[r]++:e[r]=1
+}),e},r.debounce=function(n,t,r){function e(){f=W,r||(o=n.apply(i,u))}var u,o,i,f;return function(){var a=r&&!f;return u=arguments,i=this,clearTimeout(f),f=setTimeout(e,t),a&&(o=n.apply(i,u)),o}},r.defaults=mr,r.defer=V,r.delay=function(n,r){var e=v(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},r.difference=function(n){for(var t=-1,r=n?n.length:0,u=xt.apply(ut,arguments),u=e(u,r),o=[];++t<r;){var i=n[t];u(i)||o.push(i)}return o},r.filter=N,r.flatten=P,r.forEach=$,r.forIn=lr,r.forOwn=pr,r.functions=_,r.groupBy=function(n,t,r){var e={};
+return t=f(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",(St.call(e,r)?e[r]:e[r]=[]).push(n)}),e},r.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=u;for(t=f(t,r);o--&&t(n[o],o,n);)e++}else e=t==W||r?1:t||e;return v(n,0,Dt(qt(0,u-e),u))},r.intersection=function(n){var t=arguments,r=t.length,u={0:{}},o=-1,i=n?n.length:0,f=100<=i,a=[],c=a;n:for(;++o<i;){var l=n[o];if(f)var p=l+"",p=St.call(u[0],p)?!(c=u[0][p]):c=u[0][p]=[];if(p||0>z(c,l)){f&&c.push(l);for(var s=r;--s;)if(!(u[s]||(u[s]=e(t[s],0,100)))(l))continue n;
+a.push(l)}}return a},r.invert=b,r.invoke=function(n,t){var r=v(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);return $(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},r.keys=vr,r.map=F,r.max=q,r.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return St.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},r.merge=S,r.min=function(n,t,r){var e=1/0,o=e;if(!t&&sr(n)){r=-1;for(var i=n.length;++r<i;){var a=n[r];a<o&&(o=a)
+}}else t=!t&&A(n)?u:f(t,r),cr(n,function(n,r,u){r=t(n,r,u),r<e&&(e=r,o=n)});return o},r.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]}return u},r.omit=function(n,t,r){var e=typeof t=="function",u={};if(e)t=f(t,r);else var o=xt.apply(ut,arguments);return lr(n,function(n,r,i){(e?!t(n,r,i):0>z(o,r,1))&&(u[r]=n)}),u},r.once=function(n){var t,r;return function(){return t?r:(t=Q,r=n.apply(this,arguments),n=W,r)}},r.pairs=function(n){for(var t=-1,r=vr(n),e=r.length,u=Array(e);++t<e;){var o=r[t];
+u[t]=[o,n[o]]}return u},r.partial=function(n){return i(n,v(arguments,1))},r.partialRight=function(n){return i(n,v(arguments,1),W,ft)},r.pick=function(n,t,r){var e={};if(typeof t!="function")for(var u=0,o=xt.apply(ut,arguments),i=x(n)?o.length:0;++u<i;){var a=o[u];a in n&&(e[a]=n[a])}else t=f(t,r),lr(n,function(n,r,u){t(n,r,u)&&(e[r]=n)});return e},r.pluck=_r,r.range=function(n,t,r){n=+n||0,r=+r||1,t==W&&(t=n,n=0);var e=-1;t=qt(0,wt((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},r.reject=function(n,t,r){return t=f(t,r),N(n,function(n,r,e){return!t(n,r,e)
+})},r.rest=C,r.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r=Ot(Tt()*(++t+1));e[t]=e[r],e[r]=n}),e},r.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=f(t,r),$(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i},r.tap=function(n,t){return t(n),n},r.throttle=function(n,t){function r(){f=new Date,i=W,u=n.apply(o,e)}var e,u,o,i,f=0;return function(){var a=new Date,c=t-(a-f);
+return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=W,f=a,u=n.apply(o,e)),u}},r.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},r.toArray=function(n){return n&&typeof n.length=="number"?Zt&&A(n)?n.split(""):v(n):E(n)},r.union=function(){return L(xt.apply(ut,arguments))},r.uniq=L,r.values=E,r.where=br,r.without=function(n){for(var t=-1,r=n?n.length:0,u=e(arguments,1),o=[];++t<r;){var i=n[t];u(i)||o.push(i)}return o},r.wrap=function(n,t){return function(){var r=[n];
+return Et.apply(r,arguments),t.apply(this,r)}},r.zip=function(n){for(var t=-1,r=n?q(_r(arguments,"length")):0,e=Array(r);++t<r;)e[t]=_r(arguments,t);return e},r.collect=F,r.drop=C,r.each=$,r.extend=hr,r.methods=_,r.select=N,r.tail=C,r.unique=L,H(r),r.clone=d,r.cloneDeep=function(n,t,r){return d(n,Q,t,r)},r.contains=k,r.escape=function(n){return n==W?"":(n+"").replace(_t,l)},r.every=I,r.find=R,r.has=function(n,t){return n?St.call(n,t):X},r.identity=G,r.indexOf=z,r.isArguments=y,r.isArray=sr,r.isBoolean=function(n){return n===Q||n===X||kt.call(n)==Pt
+},r.isDate=function(n){return n instanceof Date||kt.call(n)==zt},r.isElement=function(n){return n?1===n.nodeType:X},r.isEmpty=function(n){var t=Q;if(!n)return t;var r=kt.call(n),e=n.length;return r==Mt||r==Ut||r==Bt||Yt&&y(n)||r==Kt&&typeof e=="number"&&w(n.splice)?!e:(pr(n,function(){return t=X}),t)},r.isEqual=j,r.isFinite=function(n){return Rt(n)&&!$t(parseFloat(n))},r.isFunction=w,r.isNaN=function(n){return O(n)&&n!=+n},r.isNull=function(n){return n===W},r.isNumber=O,r.isObject=x,r.isPlainObject=dr,r.isRegExp=function(n){return n instanceof RegExp||kt.call(n)==Lt
+},r.isString=A,r.isUndefined=function(n){return typeof n=="undefined"},r.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?qt(0,e+r):Dt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},r.mixin=H,r.noConflict=function(){return n._=ct,this},r.random=function(n,t){return n==W&&t==W&&(t=1),n=+n||0,t==W&&(t=n,n=0),n+Ot(Tt()*((+t||0)-n+1))},r.reduce=D,r.reduceRight=T,r.result=function(n,r){var e=n?n[r]:t;return w(e)?n[r]():e},r.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:vr(n).length
+},r.some=B,r.sortedIndex=K,r.template=function(n,e,u){var o=r.templateSettings;n||(n=""),u=mr({},u,o);var i,f=mr({},u.imports,o.imports),o=vr(f),f=E(f),a=0,l=u.interpolate||dt,p="__p+='";n.replace(RegExp((u.escape||dt).source+"|"+l.source+"|"+(l===mt?ht:dt).source+"|"+(u.evaluate||dt).source+"|$","g"),function(t,r,e,u,o,f){return e||(e=u),p+=n.slice(a,f).replace(bt,c),r&&(p+="'+__e("+r+")+'"),o&&(i=Q,p+="';"+o+";__p+='"),e&&(p+="'+((__t=("+e+"))==null?'':__t)+'"),a=f+t.length,t}),p+="';\n",l=u=u.variable,l||(u="obj",p="with("+u+"){"+p+"}"),p=(i?p.replace(pt,""):p).replace(st,"$1").replace(vt,"$1;"),p="function("+u+"){"+(l?"":u+"||("+u+"={});")+"var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+p+"return __p}";
+try{var s=Function(o,"return "+p).apply(t,f)}catch(v){throw v.source=p,v}return e?s(e):(s.source=p,s)},r.unescape=function(n){return n==W?"":(n+"").replace(lt,g)},r.uniqueId=function(n){var t=++it;return(n==W?"":n+"")+t},r.all=I,r.any=B,r.detect=R,r.foldl=D,r.foldr=T,r.include=k,r.inject=D,pr(r,function(n,t){r.prototype[t]||(r.prototype[t]=function(){var t=[this.__wrapped__];return Et.apply(t,arguments),n.apply(r,t)})}),r.first=M,r.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=u;
+for(t=f(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==W||r)return n[u-1];return v(n,qt(0,u-e))}},r.take=M,r.head=M,pr(r,function(n,t){r.prototype[t]||(r.prototype[t]=function(t,e){var u=n(this.__wrapped__,t,e);return t==W||e&&typeof t!="function"?u:new r(u)})}),r.VERSION="1.0.1",r.prototype.toString=function(){return this.__wrapped__+""},r.prototype.value=J,r.prototype.valueOf=J,cr(["join","pop","shift"],function(n){var t=ut[n];r.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)}}),cr(["push","reverse","sort","unshift"],function(n){var t=ut[n];
+r.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),cr(["concat","slice","splice"],function(n){var t=ut[n];r.prototype[n]=function(){return new r(t.apply(this.__wrapped__,arguments))}}),Qt&&cr(["pop","shift","splice"],function(n){var t=ut[n],e="splice"==n;r.prototype[n]=function(){var n=this.__wrapped__,u=t.apply(n,arguments);return 0===n.length&&delete n[0],e?new r(u):u}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=r,define(function(){return r
+})):Y?Z?(Z.exports=r)._=r:Y._=r:n._=r})(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.js	(revision 533)
@@ -0,0 +1,4983 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 (Custom Build) <http://lodash.com/>
+ * Build: `lodash modern -o ./dist/lodash.js`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function(window, undefined) {
+
+  /** Detect free variable `exports` */
+  var freeExports = typeof exports == 'object' && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
+
+  /** Detect free variable `global` and use it as `window` */
+  var freeGlobal = typeof global == 'object' && global;
+  if (freeGlobal.global === freeGlobal) {
+    window = freeGlobal;
+  }
+
+  /** Used for array and object method references */
+  var arrayRef = [],
+      objectRef = {};
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = objectRef;
+
+  /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
+  var largeArraySize = 30;
+
+  /** Used to restore the original `_` reference in `noConflict` */
+  var oldDash = window._;
+
+  /** Used to match HTML entities */
+  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detect if a method is native */
+  var reNative = RegExp('^' +
+    (objectRef.valueOf + '')
+      .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+      .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
+  );
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to match HTML characters */
+  var reUnescapedHtml = /[&<>"']/g;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** Native method shortcuts */
+  var ceil = Math.ceil,
+      concat = arrayRef.concat,
+      floor = Math.floor,
+      getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+      hasOwnProperty = objectRef.hasOwnProperty,
+      push = arrayRef.push,
+      toString = objectRef.toString;
+
+  /* Native method shortcuts for methods with the same name as other `lodash` methods */
+  var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
+      nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
+      nativeIsFinite = window.isFinite,
+      nativeIsNaN = window.isNaN,
+      nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+      nativeMax = Math.max,
+      nativeMin = Math.min,
+      nativeRandom = Math.random;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Detect various environments */
+  var isIeOpera = !!window.attachEvent,
+      isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
+
+  /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
+  var isBindFast = nativeBind && !isV8;
+
+  /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
+  var isKeysFast = nativeKeys && (isIeOpera || isV8);
+
+  /** Used to identify object classifications that `_.clone` supports */
+  var cloneableClasses = {};
+  cloneableClasses[funcClass] = false;
+  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
+  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
+  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
+
+  /** Used to lookup a built-in constructor by [[Class]] */
+  var ctorByClass = {};
+  ctorByClass[arrayClass] = Array;
+  ctorByClass[boolClass] = Boolean;
+  ctorByClass[dateClass] = Date;
+  ctorByClass[objectClass] = Object;
+  ctorByClass[numberClass] = Number;
+  ctorByClass[regexpClass] = RegExp;
+  ctorByClass[stringClass] = String;
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object, that wraps the given `value`, to enable method
+   * chaining.
+   *
+   * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+   * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+   * and `unshift`
+   *
+   * The chainable wrapper functions are:
+   * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
+   * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
+   * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
+   * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
+   * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+   * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
+   * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
+   * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
+   *
+   * The non-chainable wrapper functions are:
+   * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
+   * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
+   * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
+   * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
+   * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
+   * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
+   *
+   * The wrapper functions `first` and `last` return wrapped values when `n` is
+   * passed, otherwise they return unwrapped values.
+   *
+   * @name _
+   * @constructor
+   * @category Chaining
+   * @param {Mixed} value The value to wrap in a `lodash` instance.
+   * @returns {Object} Returns a `lodash` instance.
+   */
+  function lodash(value) {
+    // exit early if already wrapped, even if wrapped by a different `lodash` constructor
+    if (value && typeof value == 'object' && value.__wrapped__) {
+      return value;
+    }
+    // allow invoking `lodash` without the `new` operator
+    if (!(this instanceof lodash)) {
+      return new lodash(value);
+    }
+    this.__wrapped__ = value;
+  }
+
+  /**
+   * By default, the template delimiters used by Lo-Dash are similar to those in
+   * embedded Ruby (ERB). Change the following template settings to use alternative
+   * delimiters.
+   *
+   * @static
+   * @memberOf _
+   * @type Object
+   */
+  lodash.templateSettings = {
+
+    /**
+     * Used to detect `data` property values to be HTML-escaped.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'escape': /<%-([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect code to be evaluated.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'evaluate': /<%([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect `data` property values to inject.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'interpolate': reInterpolate,
+
+    /**
+     * Used to reference the data object in the template text.
+     *
+     * @memberOf _.templateSettings
+     * @type String
+     */
+    'variable': '',
+
+    /**
+     * Used to import variables into the compiled template.
+     *
+     * @memberOf _.templateSettings
+     * @type Object
+     */
+    'imports': {
+
+      /**
+       * A reference to the `lodash` function.
+       *
+       * @memberOf _.templateSettings.imports
+       * @type Function
+       */
+      '_': lodash
+    }
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The template used to create iterator functions.
+   *
+   * @private
+   * @param {Obect} data The data object used to populate the text.
+   * @returns {String} Returns the interpolated text.
+   */
+  var iteratorTemplate = function(obj) {
+    
+    var __p = 'var index, iterable = ' +
+    (obj.firstArg ) +
+    ', result = iterable;\nif (!iterable) return result;\n' +
+    (obj.top ) +
+    ';\n';
+     if (obj.arrays) {
+    __p += 'var length = iterable.length; index = -1;\nif (' +
+    (obj.arrays ) +
+    ') {\n  while (++index < length) {\n    ' +
+    (obj.loop ) +
+    '\n  }\n}\nelse {  ';
+     } ;
+    
+     if (obj.isKeysFast && obj.useHas) {
+    __p += '\n  var ownIndex = -1,\n      ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n      length = ownProps.length;\n\n  while (++ownIndex < length) {\n    index = ownProps[ownIndex];\n    ' +
+    (obj.loop ) +
+    '\n  }  ';
+     } else {
+    __p += '\n  for (index in iterable) {';
+        if (obj.useHas) {
+    __p += '\n    if (';
+          if (obj.useHas) {
+    __p += 'hasOwnProperty.call(iterable, index)';
+     }    ;
+    __p += ') {    ';
+     } ;
+    __p += 
+    (obj.loop ) +
+    ';    ';
+     if (obj.useHas) {
+    __p += '\n    }';
+     } ;
+    __p += '\n  }  ';
+     } ;
+    
+     if (obj.arrays) {
+    __p += '\n}';
+     } ;
+    __p += 
+    (obj.bottom ) +
+    ';\nreturn result';
+    
+    
+    return __p
+  };
+
+  /** Reusable iterator options for `assign` and `defaults` */
+  var defaultsIteratorOptions = {
+    'args': 'object, source, guard',
+    'top':
+      'var args = arguments,\n' +
+      '    argsIndex = 0,\n' +
+      "    argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
+      'while (++argsIndex < argsLength) {\n' +
+      '  iterable = args[argsIndex];\n' +
+      '  if (iterable && objectTypes[typeof iterable]) {',
+    'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
+    'bottom': '  }\n}'
+  };
+
+  /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
+  var eachIteratorOptions = {
+    'args': 'collection, callback, thisArg',
+    'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
+    'arrays': "typeof length == 'number'",
+    'loop': 'if (callback(iterable[index], index, collection) === false) return result'
+  };
+
+  /** Reusable iterator options for `forIn` and `forOwn` */
+  var forOwnIteratorOptions = {
+    'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
+    'arrays': false
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function optimized to search large arrays for a given `value`,
+   * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @param {Number} [largeSize=30] The length at which an array is considered large.
+   * @returns {Boolean} Returns `true`, if `value` is found, else `false`.
+   */
+  function cachedContains(array, fromIndex, largeSize) {
+    fromIndex || (fromIndex = 0);
+
+    var length = array.length,
+        isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
+
+    if (isLarge) {
+      var cache = {},
+          index = fromIndex - 1;
+
+      while (++index < length) {
+        // manually coerce `value` to a string because `hasOwnProperty`, in some
+        // older versions of Firefox, coerces objects incorrectly
+        var key = array[index] + '';
+        (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
+      }
+    }
+    return function(value) {
+      if (isLarge) {
+        var key = value + '';
+        return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
+      }
+      return indexOf(array, value, fromIndex) > -1;
+    }
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default `callback` when a given
+   * `collection` is a string value.
+   *
+   * @private
+   * @param {String} value The character to inspect.
+   * @returns {Number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` values, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {Number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ai = a.index,
+        bi = b.index;
+
+    a = a.criteria;
+    b = b.criteria;
+
+    // ensure a stable sort in V8 and other engines
+    // http://code.google.com/p/v8/issues/detail?id=90
+    if (a !== b) {
+      if (a > b || typeof a == 'undefined') {
+        return 1;
+      }
+      if (a < b || typeof b == 'undefined') {
+        return -1;
+      }
+    }
+    return ai < bi ? -1 : 1;
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this` binding
+   * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
+   * bound function.
+   *
+   * @private
+   * @param {Function|String} func The function to bind or the method name.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Array} partialArgs An array of arguments to be partially applied.
+   * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
+   * @returns {Function} Returns the new bound function.
+   */
+  function createBound(func, thisArg, partialArgs, rightIndicator) {
+    var isFunc = isFunction(func),
+        isPartial = !partialArgs,
+        key = thisArg;
+
+    // juggle arguments
+    if (isPartial) {
+      partialArgs = thisArg;
+    }
+    if (!isFunc) {
+      thisArg = func;
+    }
+
+    function bound() {
+      // `Function#bind` spec
+      // http://es5.github.com/#x15.3.4.5
+      var args = arguments,
+          thisBinding = isPartial ? this : thisArg;
+
+      if (!isFunc) {
+        func = thisArg[key];
+      }
+      if (partialArgs.length) {
+        args = args.length
+          ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
+          : partialArgs;
+      }
+      if (this instanceof bound) {
+        // ensure `new bound` is an instance of `bound` and `func`
+        noop.prototype = func.prototype;
+        thisBinding = new noop;
+        noop.prototype = null;
+
+        // mimic the constructor's `return` behavior
+        // http://es5.github.com/#x13.2.2
+        var result = func.apply(thisBinding, args);
+        return isObject(result) ? result : thisBinding;
+      }
+      return func.apply(thisBinding, args);
+    }
+    return bound;
+  }
+
+  /**
+   * Produces a callback bound to an optional `thisArg`. If `func` is a property
+   * name, the created callback will return the property value for a given element.
+   * If `func` is an object, the created callback will return `true` for elements
+   * that contain the equivalent object properties, otherwise it will return `false`.
+   *
+   * @private
+   * @param {Mixed} [func=identity] The value to convert to a callback.
+   * @param {Mixed} [thisArg] The `this` binding of the created callback.
+   * @param {Number} [argCount=3] The number of arguments the callback accepts.
+   * @returns {Function} Returns a callback function.
+   */
+  function createCallback(func, thisArg, argCount) {
+    if (func == null) {
+      return identity;
+    }
+    var type = typeof func;
+    if (type != 'function') {
+      if (type != 'object') {
+        return function(object) {
+          return object[func];
+        };
+      }
+      var props = keys(func);
+      return function(object) {
+        var length = props.length,
+            result = false;
+        while (length--) {
+          if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+    if (typeof thisArg != 'undefined') {
+      if (argCount === 1) {
+        return function(value) {
+          return func.call(thisArg, value);
+        };
+      }
+      if (argCount === 2) {
+        return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+      }
+      if (argCount === 4) {
+        return function(accumulator, value, index, object) {
+          return func.call(thisArg, accumulator, value, index, object);
+        };
+      }
+      return function(value, index, object) {
+        return func.call(thisArg, value, index, object);
+      };
+    }
+    return func;
+  }
+
+  /**
+   * Creates compiled iteration functions.
+   *
+   * @private
+   * @param {Object} [options1, options2, ...] The compile options object(s).
+   *  arrays - A string of code to determine if the iterable is an array or array-like.
+   *  useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
+   *  args - A string of comma separated arguments the iteration function will accept.
+   *  top - A string of code to execute before the iteration branches.
+   *  loop - A string of code to execute in the object loop.
+   *  bottom - A string of code to execute after the iteration branches.
+   *
+   * @returns {Function} Returns the compiled function.
+   */
+  function createIterator() {
+    var data = {
+      // support properties
+      'isKeysFast': isKeysFast,
+
+      // iterator options
+      'arrays': 'isArray(iterable)',
+      'bottom': '',
+      'loop': '',
+      'top': '',
+      'useHas': true
+    };
+
+    // merge options into a template data object
+    for (var object, index = 0; object = arguments[index]; index++) {
+      for (var key in object) {
+        data[key] = object[key];
+      }
+    }
+    var args = data.args;
+    data.firstArg = /^[^,]+/.exec(args)[0];
+
+    // create the function factory
+    var factory = Function(
+        'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
+        'objectTypes, nativeKeys',
+      'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
+    );
+    // return the compiled function
+    return factory(
+      createCallback, hasOwnProperty, isArguments, isArray, isString,
+      objectTypes, nativeKeys
+    );
+  }
+
+  /**
+   * A function compiled to iterate `arguments` objects, arrays, objects, and
+   * strings consistenly across environments, executing the `callback` for each
+   * element in the `collection`. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, index|key, collection). Callbacks may exit
+   * iteration early by explicitly returning `false`.
+   *
+   * @private
+   * @type Function
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   */
+  var each = createIterator(eachIteratorOptions);
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Used by `escape` to convert characters to HTML entities.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeHtmlChar(match) {
+    return htmlEscapes[match];
+  }
+
+  /**
+   * Checks if `value` is a DOM node in IE < 9.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
+   */
+  function isNode(value) {
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings
+    return typeof value.toString != 'function' && typeof (value + '') == 'string';
+  }
+
+  /**
+   * A no-operation function.
+   *
+   * @private
+   */
+  function noop() {
+    // no operation performed
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used, instead of `Array#slice`, to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|String} collection The collection to slice.
+   * @param {Number} start The start index.
+   * @param {Number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /**
+   * Used by `unescape` to convert HTML entities to characters.
+   *
+   * @private
+   * @param {String} match The matched character to unescape.
+   * @returns {String} Returns the unescaped character.
+   */
+  function unescapeHtmlChar(match) {
+    return htmlUnescapes[match];
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if `value` is an `arguments` object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
+   * @example
+   *
+   * (function() { return _.isArguments(arguments); })(1, 2, 3);
+   * // => true
+   *
+   * _.isArguments([1, 2, 3]);
+   * // => false
+   */
+  function isArguments(value) {
+    return toString.call(value) == argsClass;
+  }
+
+  /**
+   * Iterates over `object`'s own and inherited enumerable properties, executing
+   * the `callback` for each property. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, key, object). Callbacks may exit iteration
+   * early by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * function Dog(name) {
+   *   this.name = name;
+   * }
+   *
+   * Dog.prototype.bark = function() {
+   *   alert('Woof, woof!');
+   * };
+   *
+   * _.forIn(new Dog('Dagny'), function(value, key) {
+   *   alert(key);
+   * });
+   * // => alerts 'name' and 'bark' (order is not guaranteed)
+   */
+  var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
+    'useHas': false
+  });
+
+  /**
+   * Iterates over an object's own enumerable properties, executing the `callback`
+   * for each property. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
+   * returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+   *   alert(key);
+   * });
+   * // => alerts '0', '1', and 'length' (order is not guaranteed)
+   */
+  var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
+
+  /**
+   * Checks if `value` is an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
+   * @example
+   *
+   * (function() { return _.isArray(arguments); })();
+   * // => false
+   *
+   * _.isArray([1, 2, 3]);
+   * // => true
+   */
+  var isArray = nativeIsArray || function(value) {
+    // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
+    // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
+    return value instanceof Array || toString.call(value) == arrayClass;
+  };
+
+  /**
+   * Creates an array composed of the own enumerable property names of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   * @example
+   *
+   * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => ['one', 'two', 'three'] (order is not guaranteed)
+   */
+  var keys = !nativeKeys ? shimKeys : function(object) {
+    if (!isObject(object)) {
+      return [];
+    }
+    return nativeKeys(object);
+  };
+
+  /**
+   * A fallback implementation of `isPlainObject` that checks if a given `value`
+   * is an object created by the `Object` constructor, assuming objects created
+   * by the `Object` constructor have no inherited enumerable properties and that
+   * there are no `Object.prototype` extensions.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   */
+  function shimIsPlainObject(value) {
+    // avoid non-objects and false positives for `arguments` objects
+    var result = false;
+    if (!(value && typeof value == 'object') || isArguments(value)) {
+      return result;
+    }
+    // check that the constructor is `Object` (i.e. `Object instanceof Object`)
+    var ctor = value.constructor;
+    if ((!isFunction(ctor)) || ctor instanceof ctor) {
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return result === false || hasOwnProperty.call(value, result);
+    }
+    return result;
+  }
+
+  /**
+   * A fallback implementation of `Object.keys` that produces an array of the
+   * given object's own enumerable property names.
+   *
+   * @private
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   */
+  function shimKeys(object) {
+    var result = [];
+    forOwn(object, function(value, key) {
+      result.push(key);
+    });
+    return result;
+  }
+
+  /**
+   * Used to convert characters to HTML entities:
+   *
+   * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+   * don't require escaping in HTML and have no special meaning unless they're part
+   * of a tag or an unquoted attribute value.
+   * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+   */
+  var htmlEscapes = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#39;'
+  };
+
+  /** Used to convert HTML entities to characters */
+  var htmlUnescapes = invert(htmlEscapes);
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object. Subsequent sources will overwrite propery assignments of previous
+   * sources. If a `callback` function is passed, it will be executed to produce
+   * the assigned values. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @alias extend
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize assigning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * _.assign({ 'name': 'moe' }, { 'age': 40 });
+   * // => { 'name': 'moe', 'age': 40 }
+   *
+   * var defaults = _.partialRight(_.assign, function(a, b) {
+   *   return typeof a == 'undefined' ? b : a;
+   * });
+   *
+   * var food = { 'name': 'apple' };
+   * defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  var assign = createIterator(defaultsIteratorOptions, {
+    'top':
+      defaultsIteratorOptions.top.replace(';',
+        ';\n' +
+        "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
+        '  var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
+        "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
+        '  callback = args[--argsLength];\n' +
+        '}'
+      ),
+    'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
+  });
+
+  /**
+   * Creates a clone of `value`. If `deep` is `true`, nested objects will also
+   * be cloned, otherwise they will be assigned by reference. If a `callback`
+   * function is passed, it will be executed to produce the cloned values. If
+   * `callback` returns `undefined`, cloning will be handled by the method instead.
+   * The `callback` is bound to `thisArg` and invoked with one argument; (value).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to clone.
+   * @param {Boolean} [deep=false] A flag to indicate a deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
+   * @returns {Mixed} Returns the cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var shallow = _.clone(stooges);
+   * shallow[0] === stooges[0];
+   * // => true
+   *
+   * var deep = _.clone(stooges, true);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * _.mixin({
+   *   'clone': _.partialRight(_.clone, function(value) {
+   *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+   *   })
+   * });
+   *
+   * var clone = _.clone(document.body);
+   * clone.childNodes.length;
+   * // => 0
+   */
+  function clone(value, deep, callback, thisArg, stackA, stackB) {
+    var result = value;
+
+    // allows working with "Collections" methods without using their `callback`
+    // argument, `index|key`, for this method's `callback`
+    if (typeof deep == 'function') {
+      thisArg = callback;
+      callback = deep;
+      deep = false;
+    }
+    if (typeof callback == 'function') {
+      callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
+      result = callback(result);
+
+      var done = typeof result != 'undefined';
+      if (!done) {
+        result = value;
+      }
+    }
+    // inspect [[Class]]
+    var isObj = isObject(result);
+    if (isObj) {
+      var className = toString.call(result);
+      if (!cloneableClasses[className]) {
+        return result;
+      }
+      var isArr = isArray(result);
+    }
+    // shallow clone
+    if (!isObj || !deep) {
+      return isObj && !done
+        ? (isArr ? slice(result) : assign({}, result))
+        : result;
+    }
+    var ctor = ctorByClass[className];
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        return done ? result : new ctor(+result);
+
+      case numberClass:
+      case stringClass:
+        return done ? result : new ctor(result);
+
+      case regexpClass:
+        return done ? result : ctor(result.source, reFlags.exec(result));
+    }
+    // check for circular references and return corresponding clone
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == value) {
+        return stackB[length];
+      }
+    }
+    // init cloned object
+    if (!done) {
+      result = isArr ? ctor(result.length) : {};
+
+      // add array properties assigned by `RegExp#exec`
+      if (isArr) {
+        if (hasOwnProperty.call(value, 'index')) {
+          result.index = value.index;
+        }
+        if (hasOwnProperty.call(value, 'input')) {
+          result.input = value.input;
+        }
+      }
+    }
+    // add the source value to the stack of traversed objects
+    // and associate it with its clone
+    stackA.push(value);
+    stackB.push(result);
+
+    // recursively populate clone (susceptible to call stack limits)
+    (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
+      result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
+    });
+
+    return result;
+  }
+
+  /**
+   * Creates a deep clone of `value`. If a `callback` function is passed, it will
+   * be executed to produce the cloned values. If `callback` returns the value it
+   * was passed, cloning will be handled by the method instead. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * Note: This function is loosely based on the structured clone algorithm. Functions
+   * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+   * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+   * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the deep cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var deep = _.cloneDeep(stooges);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * var view = {
+   *   'label': 'docs',
+   *   'node': element
+   * };
+   *
+   * var clone = _.cloneDeep(view, function(value) {
+   *   return _.isElement(value) ? value.cloneNode(true) : value;
+   * });
+   *
+   * clone.node == view.node;
+   * // => false
+   */
+  function cloneDeep(value, callback, thisArg) {
+    return clone(value, true, callback, thisArg);
+  }
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object for all destination properties that resolve to `undefined`. Once a
+   * property is set, additional defaults of the same property will be ignored.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param- {Object} [guard] Internally used to allow working with `_.reduce`
+   *  without using its callback's `key` and `object` arguments as sources.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var food = { 'name': 'apple' };
+   * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  var defaults = createIterator(defaultsIteratorOptions);
+
+  /**
+   * Creates a sorted array of all enumerable properties, own and inherited,
+   * of `object` that have function values.
+   *
+   * @static
+   * @memberOf _
+   * @alias methods
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names that have function values.
+   * @example
+   *
+   * _.functions(_);
+   * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+   */
+  function functions(object) {
+    var result = [];
+    forIn(object, function(value, key) {
+      if (isFunction(value)) {
+        result.push(key);
+      }
+    });
+    return result.sort();
+  }
+
+  /**
+   * Checks if the specified object `property` exists and is a direct property,
+   * instead of an inherited property.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to check.
+   * @param {String} property The property to check for.
+   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+   * @example
+   *
+   * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+   * // => true
+   */
+  function has(object, property) {
+    return object ? hasOwnProperty.call(object, property) : false;
+  }
+
+  /**
+   * Creates an object composed of the inverted keys and values of the given `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to invert.
+   * @returns {Object} Returns the created inverted object.
+   * @example
+   *
+   *  _.invert({ 'first': 'moe', 'second': 'larry' });
+   * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
+   */
+  function invert(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      result[object[key]] = key;
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is a boolean value.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
+   * @example
+   *
+   * _.isBoolean(null);
+   * // => false
+   */
+  function isBoolean(value) {
+    return value === true || value === false || toString.call(value) == boolClass;
+  }
+
+  /**
+   * Checks if `value` is a date.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
+   * @example
+   *
+   * _.isDate(new Date);
+   * // => true
+   */
+  function isDate(value) {
+    return value instanceof Date || toString.call(value) == dateClass;
+  }
+
+  /**
+   * Checks if `value` is a DOM element.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
+   * @example
+   *
+   * _.isElement(document.body);
+   * // => true
+   */
+  function isElement(value) {
+    return value ? value.nodeType === 1 : false;
+  }
+
+  /**
+   * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+   * length of `0` and objects with no own enumerable properties are considered
+   * "empty".
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Array|Object|String} value The value to inspect.
+   * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
+   * @example
+   *
+   * _.isEmpty([1, 2, 3]);
+   * // => false
+   *
+   * _.isEmpty({});
+   * // => true
+   *
+   * _.isEmpty('');
+   * // => true
+   */
+  function isEmpty(value) {
+    var result = true;
+    if (!value) {
+      return result;
+    }
+    var className = toString.call(value),
+        length = value.length;
+
+    if ((className == arrayClass || className == stringClass ||
+        className == argsClass) ||
+        (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+      return !length;
+    }
+    forOwn(value, function() {
+      return (result = false);
+    });
+    return result;
+  }
+
+  /**
+   * Performs a deep comparison between two values to determine if they are
+   * equivalent to each other. If `callback` is passed, it will be executed to
+   * compare values. If `callback` returns `undefined`, comparisons will be handled
+   * by the method instead. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (a, b).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} a The value to compare.
+   * @param {Mixed} b The other value to compare.
+   * @param {Function} [callback] The function to customize comparing values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
+   * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
+   * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
+   * @example
+   *
+   * var moe = { 'name': 'moe', 'age': 40 };
+   * var copy = { 'name': 'moe', 'age': 40 };
+   *
+   * moe == copy;
+   * // => false
+   *
+   * _.isEqual(moe, copy);
+   * // => true
+   *
+   * var words = ['hello', 'goodbye'];
+   * var otherWords = ['hi', 'goodbye'];
+   *
+   * _.isEqual(words, otherWords, function(a, b) {
+   *   var reGreet = /^(?:hello|hi)$/i,
+   *       aGreet = _.isString(a) && reGreet.test(a),
+   *       bGreet = _.isString(b) && reGreet.test(b);
+   *
+   *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+   * });
+   * // => true
+   */
+  function isEqual(a, b, callback, thisArg, stackA, stackB) {
+    // used to indicate that when comparing objects, `a` has at least the properties of `b`
+    var whereIndicator = callback === indicatorObject;
+    if (callback && !whereIndicator) {
+      callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
+      var result = callback(a, b);
+      if (typeof result != 'undefined') {
+        return !!result;
+      }
+    }
+    // exit early for identical values
+    if (a === b) {
+      // treat `+0` vs. `-0` as not equal
+      return a !== 0 || (1 / a == 1 / b);
+    }
+    var type = typeof a,
+        otherType = typeof b;
+
+    // exit early for unlike primitive values
+    if (a === a &&
+        (!a || (type != 'function' && type != 'object')) &&
+        (!b || (otherType != 'function' && otherType != 'object'))) {
+      return false;
+    }
+    // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
+    // http://es5.github.com/#x15.3.4.4
+    if (a == null || b == null) {
+      return a === b;
+    }
+    // compare [[Class]] names
+    var className = toString.call(a),
+        otherClass = toString.call(b);
+
+    if (className == argsClass) {
+      className = objectClass;
+    }
+    if (otherClass == argsClass) {
+      otherClass = objectClass;
+    }
+    if (className != otherClass) {
+      return false;
+    }
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        // coerce dates and booleans to numbers, dates to milliseconds and booleans
+        // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
+        return +a == +b;
+
+      case numberClass:
+        // treat `NaN` vs. `NaN` as equal
+        return a != +a
+          ? b != +b
+          // but treat `+0` vs. `-0` as not equal
+          : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+      case regexpClass:
+      case stringClass:
+        // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
+        // treat string primitives and their corresponding object instances as equal
+        return a == b + '';
+    }
+    var isArr = className == arrayClass;
+    if (!isArr) {
+      // unwrap any `lodash` wrapped values
+      if (a.__wrapped__ || b.__wrapped__) {
+        return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
+      }
+      // exit for functions and DOM nodes
+      if (className != objectClass) {
+        return false;
+      }
+      // in older versions of Opera, `arguments` objects have `Array` constructors
+      var ctorA = a.constructor,
+          ctorB = b.constructor;
+
+      // non `Object` object instances with different constructors are not equal
+      if (ctorA != ctorB && !(
+            isFunction(ctorA) && ctorA instanceof ctorA &&
+            isFunction(ctorB) && ctorB instanceof ctorB
+          )) {
+        return false;
+      }
+    }
+    // assume cyclic structures are equal
+    // the algorithm for detecting cyclic structures is adapted from ES 5.1
+    // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == a) {
+        return stackB[length] == b;
+      }
+    }
+    var size = 0;
+    result = true;
+
+    // add `a` and `b` to the stack of traversed objects
+    stackA.push(a);
+    stackB.push(b);
+
+    // recursively compare objects and arrays (susceptible to call stack limits)
+    if (isArr) {
+      length = a.length;
+      size = b.length;
+
+      // compare lengths to determine if a deep comparison is necessary
+      result = size == a.length;
+      if (!result && !whereIndicator) {
+        return result;
+      }
+      // deep compare the contents, ignoring non-numeric properties
+      while (size--) {
+        var index = length,
+            value = b[size];
+
+        if (whereIndicator) {
+          while (index--) {
+            if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
+              break;
+            }
+          }
+        } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
+          break;
+        }
+      }
+      return result;
+    }
+    // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
+    // which, in this case, is more costly
+    forIn(b, function(value, key, b) {
+      if (hasOwnProperty.call(b, key)) {
+        // count the number of properties.
+        size++;
+        // deep compare each property value.
+        return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
+      }
+    });
+
+    if (result && !whereIndicator) {
+      // ensure both objects have the same number of properties
+      forIn(a, function(value, key, a) {
+        if (hasOwnProperty.call(a, key)) {
+          // `size` will be `-1` if `a` has more properties than `b`
+          return (result = --size > -1);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is, or can be coerced to, a finite number.
+   *
+   * Note: This is not the same as native `isFinite`, which will return true for
+   * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
+   * @example
+   *
+   * _.isFinite(-101);
+   * // => true
+   *
+   * _.isFinite('10');
+   * // => true
+   *
+   * _.isFinite(true);
+   * // => false
+   *
+   * _.isFinite('');
+   * // => false
+   *
+   * _.isFinite(Infinity);
+   * // => false
+   */
+  function isFinite(value) {
+    return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+  }
+
+  /**
+   * Checks if `value` is a function.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
+   * @example
+   *
+   * _.isFunction(_);
+   * // => true
+   */
+  function isFunction(value) {
+    return typeof value == 'function';
+  }
+  // fallback for older versions of Chrome and Safari
+  if (isFunction(/x/)) {
+    isFunction = function(value) {
+      return value instanceof Function || toString.call(value) == funcClass;
+    };
+  }
+
+  /**
+   * Checks if `value` is the language type of Object.
+   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
+   * @example
+   *
+   * _.isObject({});
+   * // => true
+   *
+   * _.isObject([1, 2, 3]);
+   * // => true
+   *
+   * _.isObject(1);
+   * // => false
+   */
+  function isObject(value) {
+    // check if the value is the ECMAScript language type of Object
+    // http://es5.github.com/#x8
+    // and avoid a V8 bug
+    // http://code.google.com/p/v8/issues/detail?id=2291
+    return value ? objectTypes[typeof value] : false;
+  }
+
+  /**
+   * Checks if `value` is `NaN`.
+   *
+   * Note: This is not the same as native `isNaN`, which will return `true` for
+   * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
+   * @example
+   *
+   * _.isNaN(NaN);
+   * // => true
+   *
+   * _.isNaN(new Number(NaN));
+   * // => true
+   *
+   * isNaN(undefined);
+   * // => true
+   *
+   * _.isNaN(undefined);
+   * // => false
+   */
+  function isNaN(value) {
+    // `NaN` as a primitive is the only value that is not equal to itself
+    // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+    return isNumber(value) && value != +value
+  }
+
+  /**
+   * Checks if `value` is `null`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
+   * @example
+   *
+   * _.isNull(null);
+   * // => true
+   *
+   * _.isNull(undefined);
+   * // => false
+   */
+  function isNull(value) {
+    return value === null;
+  }
+
+  /**
+   * Checks if `value` is a number.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
+   * @example
+   *
+   * _.isNumber(8.4 * 5);
+   * // => true
+   */
+  function isNumber(value) {
+    return typeof value == 'number' || toString.call(value) == numberClass;
+  }
+
+  /**
+   * Checks if a given `value` is an object created by the `Object` constructor.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   * @example
+   *
+   * function Stooge(name, age) {
+   *   this.name = name;
+   *   this.age = age;
+   * }
+   *
+   * _.isPlainObject(new Stooge('moe', 40));
+   * // => false
+   *
+   * _.isPlainObject([1, 2, 3]);
+   * // => false
+   *
+   * _.isPlainObject({ 'name': 'moe', 'age': 40 });
+   * // => true
+   */
+  var isPlainObject = function(value) {
+    if (!(value && typeof value == 'object')) {
+      return false;
+    }
+    var valueOf = value.valueOf,
+        objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+    return objProto
+      ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
+      : shimIsPlainObject(value);
+  };
+
+  /**
+   * Checks if `value` is a regular expression.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
+   * @example
+   *
+   * _.isRegExp(/moe/);
+   * // => true
+   */
+  function isRegExp(value) {
+    return value instanceof RegExp || toString.call(value) == regexpClass;
+  }
+
+  /**
+   * Checks if `value` is a string.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
+   * @example
+   *
+   * _.isString('moe');
+   * // => true
+   */
+  function isString(value) {
+    return typeof value == 'string' || toString.call(value) == stringClass;
+  }
+
+  /**
+   * Checks if `value` is `undefined`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
+   * @example
+   *
+   * _.isUndefined(void 0);
+   * // => true
+   */
+  function isUndefined(value) {
+    return typeof value == 'undefined';
+  }
+
+  /**
+   * Recursively merges own enumerable properties of the source object(s), that
+   * don't resolve to `undefined`, into the destination object. Subsequent sources
+   * will overwrite propery assignments of previous sources. If a `callback` function
+   * is passed, it will be executed to produce the merged values of the destination
+   * and source properties. If `callback` returns `undefined`, merging will be
+   * handled by the method instead. The `callback` is bound to `thisArg` and
+   * invoked with two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize merging properties.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [deepIndicator] Internally used to indicate that `stackA`
+   *  and `stackB` are arrays of traversed objects instead of source objects.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate values with their
+   *  source counterparts.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var names = {
+   *   'stooges': [
+   *     { 'name': 'moe' },
+   *     { 'name': 'larry' }
+   *   ]
+   * };
+   *
+   * var ages = {
+   *   'stooges': [
+   *     { 'age': 40 },
+   *     { 'age': 50 }
+   *   ]
+   * };
+   *
+   * _.merge(names, ages);
+   * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
+   *
+   * var food = {
+   *   'fruits': ['apple'],
+   *   'vegetables': ['beet']
+   * };
+   *
+   * var otherFood = {
+   *   'fruits': ['banana'],
+   *   'vegetables': ['carrot']
+   * };
+   *
+   * _.merge(food, otherFood, function(a, b) {
+   *   return _.isArray(a) ? a.concat(b) : undefined;
+   * });
+   * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+   */
+  function merge(object, source, deepIndicator) {
+    var args = arguments,
+        index = 0,
+        length = 2;
+
+    if (!isObject(object)) {
+      return object;
+    }
+    if (deepIndicator === indicatorObject) {
+      var callback = args[3],
+          stackA = args[4],
+          stackB = args[5];
+    } else {
+      stackA = [];
+      stackB = [];
+
+      // allows working with `_.reduce` and `_.reduceRight` without
+      // using their `callback` arguments, `index|key` and `collection`
+      if (typeof deepIndicator != 'number') {
+        length = args.length;
+      }
+      if (length > 3 && typeof args[length - 2] == 'function') {
+        callback = createCallback(args[--length - 1], args[length--], 2);
+      } else if (length > 2 && typeof args[length - 1] == 'function') {
+        callback = args[--length];
+      }
+    }
+    while (++index < length) {
+      (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
+        var found,
+            isArr,
+            result = source,
+            value = object[key];
+
+        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+          // avoid merging previously merged cyclic sources
+          var stackLength = stackA.length;
+          while (stackLength--) {
+            if ((found = stackA[stackLength] == source)) {
+              value = stackB[stackLength];
+              break;
+            }
+          }
+          if (!found) {
+            value = isArr
+              ? (isArray(value) ? value : [])
+              : (isPlainObject(value) ? value : {});
+
+            if (callback) {
+              result = callback(value, source);
+              if (typeof result != 'undefined') {
+                value = result;
+              }
+            }
+            // add `source` and associated `value` to the stack of traversed objects
+            stackA.push(source);
+            stackB.push(value);
+
+            // recursively merge objects and arrays (susceptible to call stack limits)
+            if (!callback) {
+              value = merge(value, source, indicatorObject, callback, stackA, stackB);
+            }
+          }
+        }
+        else {
+          if (callback) {
+            result = callback(value, source);
+            if (typeof result == 'undefined') {
+              result = source;
+            }
+          }
+          if (typeof result != 'undefined') {
+            value = result;
+          }
+        }
+        object[key] = value;
+      });
+    }
+    return object;
+  }
+
+  /**
+   * Creates a shallow clone of `object` excluding the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a `callback` function is passed, it will be executed
+   * for each property in the `object`, omitting the properties `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
+   *  or the function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object without the omitted properties.
+   * @example
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, 'age');
+   * // => { 'name': 'moe' }
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
+   *   return typeof value == 'number';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function omit(object, callback, thisArg) {
+    var isFunc = typeof callback == 'function',
+        result = {};
+
+    if (isFunc) {
+      callback = createCallback(callback, thisArg);
+    } else {
+      var props = concat.apply(arrayRef, arguments);
+    }
+    forIn(object, function(value, key, object) {
+      if (isFunc
+            ? !callback(value, key, object)
+            : indexOf(props, key, 1) < 0
+          ) {
+        result[key] = value;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Creates a two dimensional array of the given object's key-value pairs,
+   * i.e. `[[key1, value1], [key2, value2]]`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns new array of key-value pairs.
+   * @example
+   *
+   * _.pairs({ 'moe': 30, 'larry': 40 });
+   * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
+   */
+  function pairs(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      var key = props[index];
+      result[index] = [key, object[key]];
+    }
+    return result;
+  }
+
+  /**
+   * Creates a shallow clone of `object` composed of the specified properties.
+   * Property names may be specified as individual arguments or as arrays of property
+   * names. If `callback` is passed, it will be executed for each property in the
+   * `object`, picking the properties `callback` returns truthy for. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
+   *  per iteration or properties to pick, either as individual arguments or arrays.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object composed of the picked properties.
+   * @example
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
+   * // => { 'name': 'moe' }
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
+   *   return key.charAt(0) != '_';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function pick(object, callback, thisArg) {
+    var result = {};
+    if (typeof callback != 'function') {
+      var index = 0,
+          props = concat.apply(arrayRef, arguments),
+          length = isObject(object) ? props.length : 0;
+
+      while (++index < length) {
+        var key = props[index];
+        if (key in object) {
+          result[key] = object[key];
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg);
+      forIn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result[key] = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array composed of the own enumerable property values of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => [1, 2, 3]
+   */
+  function values(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = object[props[index]];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array of elements from the specified indexes, or keys, of the
+   * `collection`. Indexes may be specified as individual arguments or as arrays
+   * of indexes.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Array|Number|String} [index1, index2, ...] The indexes of
+   *  `collection` to retrieve, either as individual arguments or arrays.
+   * @returns {Array} Returns a new array of elements corresponding to the
+   *  provided indexes.
+   * @example
+   *
+   * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+   * // => ['a', 'c', 'e']
+   *
+   * _.at(['moe', 'larry', 'curly'], 0, 2);
+   * // => ['moe', 'curly']
+   */
+  function at(collection) {
+    var index = -1,
+        props = concat.apply(arrayRef, slice(arguments, 1)),
+        length = props.length,
+        result = Array(length);
+
+    while(++index < length) {
+      result[index] = collection[props[index]];
+    }
+    return result;
+  }
+
+  /**
+   * Checks if a given `target` element is present in a `collection` using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @alias include
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Mixed} target The value to check for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
+   * @example
+   *
+   * _.contains([1, 2, 3], 1);
+   * // => true
+   *
+   * _.contains([1, 2, 3], 1, 2);
+   * // => false
+   *
+   * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+   * // => true
+   *
+   * _.contains('curly', 'ur');
+   * // => true
+   */
+  function contains(collection, target, fromIndex) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = false;
+
+    fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+    if (typeof length == 'number') {
+      result = (isString(collection)
+        ? collection.indexOf(target, fromIndex)
+        : indexOf(collection, target, fromIndex)
+      ) > -1;
+    } else {
+      each(collection, function(value) {
+        if (++index >= fromIndex) {
+          return !(result = value === target);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the given `callback`. The corresponding value of each key
+   * is the number of times the key was returned by the `callback`. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy(['one', 'two', 'three'], 'length');
+   * // => { '3': 2, '5': 1 }
+   */
+  function countBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+    return result;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **all** elements of a
+   * `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias all
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if all elements pass the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.every([true, 1, null, 'yes'], Boolean);
+   * // => false
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.every(stooges, 'age');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.every(stooges, { 'age': 50 });
+   * // => false
+   */
+  function every(collection, callback, thisArg) {
+    var result = true;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (!(result = !!callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return (result = !!callback(value, index, collection));
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias select
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that passed the callback check.
+   * @example
+   *
+   * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [2, 4, 6]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.filter(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.filter(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   */
+  function filter(collection, callback, thisArg) {
+    var result = [];
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning the first that the `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias detect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the element that passed the callback check,
+   *  else `undefined`.
+   * @example
+   *
+   * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => 2
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },
+   *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * var veggie = _.find(food, { 'type': 'vegetable' });
+   * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
+   *
+   * // using "_.pluck" callback shorthand
+   * var healthy = _.find(food, 'organic');
+   * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
+   */
+  function find(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, index, collection) {
+      if (callback(value, index, collection)) {
+        result = value;
+        return false;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Iterates over a `collection`, executing the `callback` for each element in
+   * the `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection). Callbacks may exit iteration early
+   * by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias each
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   * @example
+   *
+   * _([1, 2, 3]).forEach(alert).join(',');
+   * // => alerts each number and returns '1,2,3'
+   *
+   * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
+   * // => alerts each number value (order is not guaranteed)
+   */
+  function forEach(collection, callback, thisArg) {
+    if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (callback(collection[index], index, collection) === false) {
+          break;
+        }
+      }
+    } else {
+      each(collection, callback, thisArg);
+    }
+    return collection;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the `callback`. The corresponding value of each key is
+   * an array of elements passed to `callback` that returned the key. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * // using "_.pluck" callback shorthand
+   * _.groupBy(['one', 'two', 'three'], 'length');
+   * // => { '3': ['one', 'two'], '5': ['three'] }
+   */
+  function groupBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+    return result;
+  }
+
+  /**
+   * Invokes the method named by `methodName` on each element in the `collection`,
+   * returning an array of the results of each invoked method. Additional arguments
+   * will be passed to each invoked method. If `methodName` is a function, it will
+   * be invoked for, and `this` bound to, each element in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|String} methodName The name of the method to invoke or
+   *  the function invoked per iteration.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+   * @returns {Array} Returns a new array of the results of each invoked method.
+   * @example
+   *
+   * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+   * // => [[1, 5, 7], [1, 2, 3]]
+   *
+   * _.invoke([123, 456], String.prototype.split, '');
+   * // => [['1', '2', '3'], ['4', '5', '6']]
+   */
+  function invoke(collection, methodName) {
+    var args = slice(arguments, 2),
+        index = -1,
+        isFunc = typeof methodName == 'function',
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+    });
+    return result;
+  }
+
+  /**
+   * Creates an array of values by running each element in the `collection`
+   * through the `callback`. The `callback` is bound to `thisArg` and invoked with
+   * three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias collect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * _.map([1, 2, 3], function(num) { return num * 3; });
+   * // => [3, 6, 9]
+   *
+   * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+   * // => [3, 6, 9] (order is not guaranteed)
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.map(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  function map(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    if (isArray(collection)) {
+      while (++index < length) {
+        result[index] = callback(collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, key, collection) {
+        result[++index] = callback(value, key, collection);
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the maximum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the maximum value.
+   * @example
+   *
+   * _.max([4, 2, 8, 6]);
+   * // => 8
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.max(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'larry', 'age': 50 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.max(stooges, 'age');
+   * // => { 'name': 'larry', 'age': 50 };
+   */
+  function max(collection, callback, thisArg) {
+    var computed = -Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value > result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = !callback && isString(collection)
+        ? charAtCallback
+        : createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current > computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the minimum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the minimum value.
+   * @example
+   *
+   * _.min([4, 2, 8, 6]);
+   * // => 2
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.min(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'moe', 'age': 40 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.min(stooges, 'age');
+   * // => { 'name': 'moe', 'age': 40 };
+   */
+  function min(collection, callback, thisArg) {
+    var computed = Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value < result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = !callback && isString(collection)
+        ? charAtCallback
+        : createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current < computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the value of a specified property from all elements in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {String} property The property to pluck.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.pluck(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  var pluck = map;
+
+  /**
+   * Reduces a `collection` to a value that is the accumulated result of running
+   * each element in the `collection` through the `callback`, where each successive
+   * `callback` execution consumes the return value of the previous execution.
+   * If `accumulator` is not passed, the first element of the `collection` will be
+   * used as the initial `accumulator` value. The `callback` is bound to `thisArg`
+   * and invoked with four arguments; (accumulator, value, index|key, collection).
+   *
+   * @static
+   * @memberOf _
+   * @alias foldl, inject
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var sum = _.reduce([1, 2, 3], function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+   *   result[key] = num * 3;
+   *   return result;
+   * }, {});
+   * // => { 'a': 3, 'b': 6, 'c': 9 }
+   */
+  function reduce(collection, callback, accumulator, thisArg) {
+    var noaccum = arguments.length < 3;
+    callback = createCallback(callback, thisArg, 4);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      if (noaccum) {
+        accumulator = collection[++index];
+      }
+      while (++index < length) {
+        accumulator = callback(accumulator, collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection)
+      });
+    }
+    return accumulator;
+  }
+
+  /**
+   * This method is similar to `_.reduce`, except that it iterates over a
+   * `collection` from right to left.
+   *
+   * @static
+   * @memberOf _
+   * @alias foldr
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var list = [[0, 1], [2, 3], [4, 5]];
+   * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+   * // => [4, 5, 2, 3, 0, 1]
+   */
+  function reduceRight(collection, callback, accumulator, thisArg) {
+    var iterable = collection,
+        length = collection ? collection.length : 0,
+        noaccum = arguments.length < 3;
+
+    if (typeof length != 'number') {
+      var props = keys(collection);
+      length = props.length;
+    }
+    callback = createCallback(callback, thisArg, 4);
+    forEach(collection, function(value, index, collection) {
+      index = props ? props[--length] : --length;
+      accumulator = noaccum
+        ? (noaccum = false, iterable[index])
+        : callback(accumulator, iterable[index], index, collection);
+    });
+    return accumulator;
+  }
+
+  /**
+   * The opposite of `_.filter`, this method returns the elements of a
+   * `collection` that `callback` does **not** return truthy for.
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that did **not** pass the
+   *  callback check.
+   * @example
+   *
+   * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [1, 3, 5]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.reject(food, 'organic');
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.reject(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   */
+  function reject(collection, callback, thisArg) {
+    callback = createCallback(callback, thisArg);
+    return filter(collection, function(value, index, collection) {
+      return !callback(value, index, collection);
+    });
+  }
+
+  /**
+   * Creates an array of shuffled `array` values, using a version of the
+   * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to shuffle.
+   * @returns {Array} Returns a new shuffled collection.
+   * @example
+   *
+   * _.shuffle([1, 2, 3, 4, 5, 6]);
+   * // => [4, 1, 6, 3, 5, 2]
+   */
+  function shuffle(collection) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      var rand = floor(nativeRandom() * (++index + 1));
+      result[index] = result[rand];
+      result[rand] = value;
+    });
+    return result;
+  }
+
+  /**
+   * Gets the size of the `collection` by returning `collection.length` for arrays
+   * and array-like objects or the number of own enumerable properties for objects.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to inspect.
+   * @returns {Number} Returns `collection.length` or number of own enumerable properties.
+   * @example
+   *
+   * _.size([1, 2]);
+   * // => 2
+   *
+   * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => 3
+   *
+   * _.size('curly');
+   * // => 5
+   */
+  function size(collection) {
+    var length = collection ? collection.length : 0;
+    return typeof length == 'number' ? length : keys(collection).length;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **any** element of a
+   * `collection`. The function returns as soon as it finds passing value, and
+   * does not iterate over the entire `collection`. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias any
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if any element passes the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.some([null, 0, 'yes', false], Boolean);
+   * // => true
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.some(food, 'organic');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.some(food, { 'type': 'meat' });
+   * // => false
+   */
+  function some(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if ((result = callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return !(result = callback(value, index, collection));
+      });
+    }
+    return !!result;
+  }
+
+  /**
+   * Creates an array of elements, sorted in ascending order by the results of
+   * running each element in the `collection` through the `callback`. This method
+   * performs a stable sort, that is, it will preserve the original sort order of
+   * equal elements. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of sorted elements.
+   * @example
+   *
+   * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+   * // => [3, 1, 2]
+   *
+   * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+   * // => [3, 1, 2]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
+   * // => ['apple', 'banana', 'strawberry']
+   */
+  function sortBy(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    forEach(collection, function(value, key, collection) {
+      result[++index] = {
+        'criteria': callback(value, key, collection),
+        'index': index,
+        'value': value
+      };
+    });
+
+    length = result.length;
+    result.sort(compareAscending);
+    while (length--) {
+      result[length] = result[length].value;
+    }
+    return result;
+  }
+
+  /**
+   * Converts the `collection` to an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to convert.
+   * @returns {Array} Returns the new converted array.
+   * @example
+   *
+   * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+   * // => [2, 3, 4]
+   */
+  function toArray(collection) {
+    if (collection && typeof collection.length == 'number') {
+      return  slice(collection);
+    }
+    return values(collection);
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * that have the given `properties`. When checking `properties`, this method
+   * performs a deep comparison between values to determine if they are equivalent
+   * to each other.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Object} properties The object of property values to filter by.
+   * @returns {Array} Returns a new array of elements that have the given `properties`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.where(stooges, { 'age': 40 });
+   * // => [{ 'name': 'moe', 'age': 40 }]
+   */
+  var where = filter;
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array with all falsey values of `array` removed. The values
+   * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.compact([0, 1, false, 2, '', 3]);
+   * // => [1, 2, 3]
+   */
+  function compact(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (value) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of `array` elements not present in the other arrays
+   * using strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Array} [array1, array2, ...] Arrays to check.
+   * @returns {Array} Returns a new array of `array` elements not present in the
+   *  other arrays.
+   * @example
+   *
+   * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+   * // => [1, 3, 4]
+   */
+  function difference(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        flattened = concat.apply(arrayRef, arguments),
+        contains = cachedContains(flattened, length),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (!contains(value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the first element of the `array`. If a number `n` is passed, the first
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the first elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias head, take
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the first element(s) of `array`.
+   * @example
+   *
+   * _.first([1, 2, 3]);
+   * // => 1
+   *
+   * _.first([1, 2, 3], 2);
+   * // => [1, 2]
+   *
+   * _.first([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [1, 2]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.first(food, 'organic');
+   * // => [{ 'name': 'banana', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.first(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
+   */
+  function first(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = createCallback(callback, thisArg);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[0];
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+  }
+
+  /**
+   * Flattens a nested array (the nesting can be to any depth). If `shallow` is
+   * truthy, `array` will only be flattened a single level.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @param {Boolean} shallow A flag to indicate only flattening a single level.
+   * @returns {Array} Returns a new flattened array.
+   * @example
+   *
+   * _.flatten([1, [2], [3, [[4]]]]);
+   * // => [1, 2, 3, 4];
+   *
+   * _.flatten([1, [2], [3, [[4]]]], true);
+   * // => [1, 2, 3, [[4]]];
+   */
+  function flatten(array, shallow) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+
+      // recursively flatten arrays (susceptible to call stack limits)
+      if (isArray(value)) {
+        push.apply(result, shallow ? value : flatten(value));
+      } else {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the index at which the first occurrence of `value` is found using
+   * strict equality for comparisons, i.e. `===`. If the `array` is already
+   * sorted, passing `true` for `fromIndex` will run a faster binary search.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
+   *  perform a binary search on a sorted `array`.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 1
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 4
+   *
+   * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+   * // => 2
+   */
+  function indexOf(array, value, fromIndex) {
+    var index = -1,
+        length = array ? array.length : 0;
+
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
+    } else if (fromIndex) {
+      index = sortedIndex(array, value);
+      return array[index] === value ? index : -1;
+    }
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Gets all but the last element of `array`. If a number `n` is passed, the
+   * last `n` elements are excluded from the result. If a `callback` function
+   * is passed, the last elements the `callback` returns truthy for are excluded
+   * from the result. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.initial([1, 2, 3]);
+   * // => [1, 2]
+   *
+   * _.initial([1, 2, 3], 2);
+   * // => [1]
+   *
+   * _.initial([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [1]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.initial(food, 'organic');
+   * // => [{ 'name': 'beet',   'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.initial(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'banana', 'type': 'fruit' }]
+   */
+  function initial(array, callback, thisArg) {
+    if (!array) {
+      return [];
+    }
+    var n = 0,
+        length = array.length;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = length;
+      callback = createCallback(callback, thisArg);
+      while (index-- && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : callback || n;
+    }
+    return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+  }
+
+  /**
+   * Computes the intersection of all the passed-in arrays using strict equality
+   * for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique elements that are present
+   *  in **all** of the arrays.
+   * @example
+   *
+   * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2]
+   */
+  function intersection(array) {
+    var args = arguments,
+        argsLength = args.length,
+        cache = { '0': {} },
+        index = -1,
+        length = array ? array.length : 0,
+        isLarge = length >= 100,
+        result = [],
+        seen = result;
+
+    outer:
+    while (++index < length) {
+      var value = array[index];
+      if (isLarge) {
+        var key = value + '';
+        var inited = hasOwnProperty.call(cache[0], key)
+          ? !(seen = cache[0][key])
+          : (seen = cache[0][key] = []);
+      }
+      if (inited || indexOf(seen, value) < 0) {
+        if (isLarge) {
+          seen.push(value);
+        }
+        var argsIndex = argsLength;
+        while (--argsIndex) {
+          if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {
+            continue outer;
+          }
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the last element of the `array`. If a number `n` is passed, the last
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the last elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the last element(s) of `array`.
+   * @example
+   *
+   * _.last([1, 2, 3]);
+   * // => 3
+   *
+   * _.last([1, 2, 3], 2);
+   * // => [2, 3]
+   *
+   * _.last([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [2, 3]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.last(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.last(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
+   */
+  function last(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = createCallback(callback, thisArg);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[length - 1];
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+  }
+
+  /**
+   * Gets the index at which the last occurrence of `value` is found using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=array.length-1] The index to search from.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 4
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 1
+   */
+  function lastIndexOf(array, value, fromIndex) {
+    var index = array ? array.length : 0;
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+    }
+    while (index--) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Creates an object composed from arrays of `keys` and `values`. Pass either
+   * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
+   * two arrays, one of `keys` and one of corresponding `values`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} keys The array of keys.
+   * @param {Array} [values=[]] The array of values.
+   * @returns {Object} Returns an object composed of the given keys and
+   *  corresponding values.
+   * @example
+   *
+   * _.object(['moe', 'larry'], [30, 40]);
+   * // => { 'moe': 30, 'larry': 40 }
+   */
+  function object(keys, values) {
+    var index = -1,
+        length = keys ? keys.length : 0,
+        result = {};
+
+    while (++index < length) {
+      var key = keys[index];
+      if (values) {
+        result[key] = values[index];
+      } else {
+        result[key[0]] = key[1];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of numbers (positive and/or negative) progressing from
+   * `start` up to but not including `end`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Number} [start=0] The start of the range.
+   * @param {Number} end The end of the range.
+   * @param {Number} [step=1] The value to increment or descrement by.
+   * @returns {Array} Returns a new range array.
+   * @example
+   *
+   * _.range(10);
+   * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+   *
+   * _.range(1, 11);
+   * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+   *
+   * _.range(0, 30, 5);
+   * // => [0, 5, 10, 15, 20, 25]
+   *
+   * _.range(0, -10, -1);
+   * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+   *
+   * _.range(0);
+   * // => []
+   */
+  function range(start, end, step) {
+    start = +start || 0;
+    step = +step || 1;
+
+    if (end == null) {
+      end = start;
+      start = 0;
+    }
+    // use `Array(length)` so V8 will avoid the slower "dictionary" mode
+    // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+    var index = -1,
+        length = nativeMax(0, ceil((end - start) / step)),
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = start;
+      start += step;
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.initial`, this method gets all but the first value of `array`.
+   * If a number `n` is passed, the first `n` values are excluded from the result.
+   * If a `callback` function is passed, the first elements the `callback` returns
+   * truthy for are excluded from the result. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias drop, tail
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.rest([1, 2, 3]);
+   * // => [2, 3]
+   *
+   * _.rest([1, 2, 3], 2);
+   * // => [3]
+   *
+   * _.rest([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [3]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.rest(food, 'organic');
+   * // => [{ 'name': 'beet', 'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.rest(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }]
+   */
+  function rest(array, callback, thisArg) {
+    if (typeof callback != 'number' && callback != null) {
+      var n = 0,
+          index = -1,
+          length = array ? array.length : 0;
+
+      callback = createCallback(callback, thisArg);
+      while (++index < length && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+    }
+    return slice(array, n);
+  }
+
+  /**
+   * Uses a binary search to determine the smallest index at which the `value`
+   * should be inserted into `array` in order to maintain the sort order of the
+   * sorted `array`. If `callback` is passed, it will be executed for `value` and
+   * each element in `array` to compute their sort ranking. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to iterate over.
+   * @param {Mixed} value The value to evaluate.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Number} Returns the index at which the value should be inserted
+   *  into `array`.
+   * @example
+   *
+   * _.sortedIndex([20, 30, 50], 40);
+   * // => 2
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+   * // => 2
+   *
+   * var dict = {
+   *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+   * };
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return dict.wordToNumber[word];
+   * });
+   * // => 2
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return this.wordToNumber[word];
+   * }, dict);
+   * // => 2
+   */
+  function sortedIndex(array, value, callback, thisArg) {
+    var low = 0,
+        high = array ? array.length : low;
+
+    // explicitly reference `identity` for better inlining in Firefox
+    callback = callback ? createCallback(callback, thisArg, 1) : identity;
+    value = callback(value);
+
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      callback(array[mid]) < value
+        ? low = mid + 1
+        : high = mid;
+    }
+    return low;
+  }
+
+  /**
+   * Computes the union of the passed-in arrays using strict equality for
+   * comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique values, in order, that are
+   *  present in one or more of the arrays.
+   * @example
+   *
+   * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2, 3, 101, 10]
+   */
+  function union() {
+    return uniq(concat.apply(arrayRef, arguments));
+  }
+
+  /**
+   * Creates a duplicate-value-free version of the `array` using strict equality
+   * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
+   * for `isSorted` will run a faster algorithm. If `callback` is passed, each
+   * element of `array` is passed through a callback` before uniqueness is computed.
+   * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias unique
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a duplicate-value-free array.
+   * @example
+   *
+   * _.uniq([1, 2, 1, 3, 1]);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 1, 2, 2, 3], true);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
+   * // => [1, 2, 3]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+   * // => [{ 'x': 1 }, { 'x': 2 }]
+   */
+  function uniq(array, isSorted, callback, thisArg) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [],
+        seen = result;
+
+    // juggle arguments
+    if (typeof isSorted == 'function') {
+      thisArg = callback;
+      callback = isSorted;
+      isSorted = false;
+    }
+    // init value cache for large arrays
+    var isLarge = !isSorted && length >= 75;
+    if (isLarge) {
+      var cache = {};
+    }
+    if (callback) {
+      seen = [];
+      callback = createCallback(callback, thisArg);
+    }
+    while (++index < length) {
+      var value = array[index],
+          computed = callback ? callback(value, index, array) : value;
+
+      if (isLarge) {
+        var key = computed + '';
+        var inited = hasOwnProperty.call(cache, key)
+          ? !(seen = cache[key])
+          : (seen = cache[key] = []);
+      }
+      if (isSorted
+            ? !index || seen[seen.length - 1] !== computed
+            : inited || indexOf(seen, computed) < 0
+          ) {
+        if (callback || isLarge) {
+          seen.push(computed);
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array with all occurrences of the passed values removed using
+   * strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to filter.
+   * @param {Mixed} [value1, value2, ...] Values to remove.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+   * // => [2, 3, 4]
+   */
+  function without(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        contains = cachedContains(arguments, 1),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (!contains(value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Groups the elements of each array at their corresponding indexes. Useful for
+   * separate data sources that are coordinated through matching array indexes.
+   * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
+   * in a similar fashion.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of grouped elements.
+   * @example
+   *
+   * _.zip(['moe', 'larry'], [30, 40], [true, false]);
+   * // => [['moe', 30, true], ['larry', 40, false]]
+   */
+  function zip(array) {
+    var index = -1,
+        length = array ? max(pluck(arguments, 'length')) : 0,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = pluck(arguments, index);
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function that is restricted to executing `func` only after it is
+   * called `n` times. The `func` is executed with the `this` binding of the
+   * created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Number} n The number of times the function must be called before
+   * it is executed.
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var renderNotes = _.after(notes.length, render);
+   * _.forEach(notes, function(note) {
+   *   note.asyncSave({ 'success': renderNotes });
+   * });
+   * // `renderNotes` is run once, after all notes have saved
+   */
+  function after(n, func) {
+    if (n < 1) {
+      return func();
+    }
+    return function() {
+      if (--n < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this`
+   * binding of `thisArg` and prepends any additional `bind` arguments to those
+   * passed to the bound function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to bind.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var func = function(greeting) {
+   *   return greeting + ' ' + this.name;
+   * };
+   *
+   * func = _.bind(func, { 'name': 'moe' }, 'hi');
+   * func();
+   * // => 'hi moe'
+   */
+  function bind(func, thisArg) {
+    // use `Function#bind` if it exists and is fast
+    // (in V8 `Function#bind` is slower except when partially applied)
+    return isBindFast || (nativeBind && arguments.length > 2)
+      ? nativeBind.call.apply(nativeBind, arguments)
+      : createBound(func, thisArg, slice(arguments, 2));
+  }
+
+  /**
+   * Binds methods on `object` to `object`, overwriting the existing method.
+   * Method names may be specified as individual arguments or as arrays of method
+   * names. If no method names are provided, all the function properties of `object`
+   * will be bound.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object to bind and assign the bound methods to.
+   * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * var view = {
+   *  'label': 'docs',
+   *  'onClick': function() { alert('clicked ' + this.label); }
+   * };
+   *
+   * _.bindAll(view);
+   * jQuery('#docs').on('click', view.onClick);
+   * // => alerts 'clicked docs', when the button is clicked
+   */
+  function bindAll(object) {
+    var funcs = concat.apply(arrayRef, arguments),
+        index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
+        length = funcs.length;
+
+    while (++index < length) {
+      var key = funcs[index];
+      object[key] = bind(object[key], object);
+    }
+    return object;
+  }
+
+  /**
+   * Creates a function that, when called, invokes the method at `object[key]`
+   * and prepends any additional `bindKey` arguments to those passed to the bound
+   * function. This method differs from `_.bind` by allowing bound functions to
+   * reference methods that will be redefined or don't yet exist.
+   * See http://michaux.ca/articles/lazy-function-definition-pattern.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object the method belongs to.
+   * @param {String} key The key of the method.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var object = {
+   *   'name': 'moe',
+   *   'greet': function(greeting) {
+   *     return greeting + ' ' + this.name;
+   *   }
+   * };
+   *
+   * var func = _.bindKey(object, 'greet', 'hi');
+   * func();
+   * // => 'hi moe'
+   *
+   * object.greet = function(greeting) {
+   *   return greeting + ', ' + this.name + '!';
+   * };
+   *
+   * func();
+   * // => 'hi, moe!'
+   */
+  function bindKey(object, key) {
+    return createBound(object, key, slice(arguments, 2));
+  }
+
+  /**
+   * Creates a function that is the composition of the passed functions,
+   * where each function consumes the return value of the function that follows.
+   * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+   * Each function is executed with the `this` binding of the composed function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} [func1, func2, ...] Functions to compose.
+   * @returns {Function} Returns the new composed function.
+   * @example
+   *
+   * var greet = function(name) { return 'hi ' + name; };
+   * var exclaim = function(statement) { return statement + '!'; };
+   * var welcome = _.compose(exclaim, greet);
+   * welcome('moe');
+   * // => 'hi moe!'
+   */
+  function compose() {
+    var funcs = arguments;
+    return function() {
+      var args = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        args = [funcs[length].apply(this, args)];
+      }
+      return args[0];
+    };
+  }
+
+  /**
+   * Creates a function that will delay the execution of `func` until after
+   * `wait` milliseconds have elapsed since the last time it was invoked. Pass
+   * `true` for `immediate` to cause debounce to invoke `func` on the leading,
+   * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
+   * the debounced function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to debounce.
+   * @param {Number} wait The number of milliseconds to delay.
+   * @param {Boolean} immediate A flag to indicate execution is on the leading
+   *  edge of the timeout.
+   * @returns {Function} Returns the new debounced function.
+   * @example
+   *
+   * var lazyLayout = _.debounce(calculateLayout, 300);
+   * jQuery(window).on('resize', lazyLayout);
+   */
+  function debounce(func, wait, immediate) {
+    var args,
+        result,
+        thisArg,
+        timeoutId;
+
+    function delayed() {
+      timeoutId = null;
+      if (!immediate) {
+        result = func.apply(thisArg, args);
+      }
+    }
+    return function() {
+      var isImmediate = immediate && !timeoutId;
+      args = arguments;
+      thisArg = this;
+
+      clearTimeout(timeoutId);
+      timeoutId = setTimeout(delayed, wait);
+
+      if (isImmediate) {
+        result = func.apply(thisArg, args);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Executes the `func` function after `wait` milliseconds. Additional arguments
+   * will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to delay.
+   * @param {Number} wait The number of milliseconds to delay execution.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * var log = _.bind(console.log, console);
+   * _.delay(log, 1000, 'logged later');
+   * // => 'logged later' (Appears after one second.)
+   */
+  function delay(func, wait) {
+    var args = slice(arguments, 2);
+    return setTimeout(function() { func.apply(undefined, args); }, wait);
+  }
+
+  /**
+   * Defers executing the `func` function until the current call stack has cleared.
+   * Additional arguments will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to defer.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * _.defer(function() { alert('deferred'); });
+   * // returns from the function before `alert` is called
+   */
+  function defer(func) {
+    var args = slice(arguments, 1);
+    return setTimeout(function() { func.apply(undefined, args); }, 1);
+  }
+  // use `setImmediate` if it's available in Node.js
+  if (isV8 && freeModule && typeof setImmediate == 'function') {
+    defer = bind(setImmediate, window);
+  }
+
+  /**
+   * Creates a function that memoizes the result of `func`. If `resolver` is
+   * passed, it will be used to determine the cache key for storing the result
+   * based on the arguments passed to the memoized function. By default, the first
+   * argument passed to the memoized function is used as the cache key. The `func`
+   * is executed with the `this` binding of the memoized function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to have its output memoized.
+   * @param {Function} [resolver] A function used to resolve the cache key.
+   * @returns {Function} Returns the new memoizing function.
+   * @example
+   *
+   * var fibonacci = _.memoize(function(n) {
+   *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+   * });
+   */
+  function memoize(func, resolver) {
+    var cache = {};
+    return function() {
+      var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
+      return hasOwnProperty.call(cache, key)
+        ? cache[key]
+        : (cache[key] = func.apply(this, arguments));
+    };
+  }
+
+  /**
+   * Creates a function that is restricted to execute `func` once. Repeat calls to
+   * the function will return the value of the first call. The `func` is executed
+   * with the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var initialize = _.once(createApplication);
+   * initialize();
+   * initialize();
+   * // `initialize` executes `createApplication` once
+   */
+  function once(func) {
+    var ran,
+        result;
+
+    return function() {
+      if (ran) {
+        return result;
+      }
+      ran = true;
+      result = func.apply(this, arguments);
+
+      // clear the `func` variable so the function may be garbage collected
+      func = null;
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with any additional
+   * `partial` arguments prepended to those passed to the new function. This
+   * method is similar to `_.bind`, except it does **not** alter the `this` binding.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var greet = function(greeting, name) { return greeting + ' ' + name; };
+   * var hi = _.partial(greet, 'hi');
+   * hi('moe');
+   * // => 'hi moe'
+   */
+  function partial(func) {
+    return createBound(func, slice(arguments, 1));
+  }
+
+  /**
+   * This method is similar to `_.partial`, except that `partial` arguments are
+   * appended to those passed to the new function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var defaultsDeep = _.partialRight(_.merge, _.defaults);
+   *
+   * var options = {
+   *   'variable': 'data',
+   *   'imports': { 'jq': $ }
+   * };
+   *
+   * defaultsDeep(options, _.templateSettings);
+   *
+   * options.variable
+   * // => 'data'
+   *
+   * options.imports
+   * // => { '_': _, 'jq': $ }
+   */
+  function partialRight(func) {
+    return createBound(func, slice(arguments, 1), null, indicatorObject);
+  }
+
+  /**
+   * Creates a function that, when executed, will only call the `func`
+   * function at most once per every `wait` milliseconds. If the throttled
+   * function is invoked more than once during the `wait` timeout, `func` will
+   * also be called on the trailing edge of the timeout. Subsequent calls to the
+   * throttled function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to throttle.
+   * @param {Number} wait The number of milliseconds to throttle executions to.
+   * @returns {Function} Returns the new throttled function.
+   * @example
+   *
+   * var throttled = _.throttle(updatePosition, 100);
+   * jQuery(window).on('scroll', throttled);
+   */
+  function throttle(func, wait) {
+    var args,
+        result,
+        thisArg,
+        timeoutId,
+        lastCalled = 0;
+
+    function trailingCall() {
+      lastCalled = new Date;
+      timeoutId = null;
+      result = func.apply(thisArg, args);
+    }
+    return function() {
+      var now = new Date,
+          remaining = wait - (now - lastCalled);
+
+      args = arguments;
+      thisArg = this;
+
+      if (remaining <= 0) {
+        clearTimeout(timeoutId);
+        timeoutId = null;
+        lastCalled = now;
+        result = func.apply(thisArg, args);
+      }
+      else if (!timeoutId) {
+        timeoutId = setTimeout(trailingCall, remaining);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that passes `value` to the `wrapper` function as its
+   * first argument. Additional arguments passed to the function are appended
+   * to those passed to the `wrapper` function. The `wrapper` is executed with
+   * the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Mixed} value The value to wrap.
+   * @param {Function} wrapper The wrapper function.
+   * @returns {Function} Returns the new function.
+   * @example
+   *
+   * var hello = function(name) { return 'hello ' + name; };
+   * hello = _.wrap(hello, function(func) {
+   *   return 'before, ' + func('moe') + ', after';
+   * });
+   * hello();
+   * // => 'before, hello moe, after'
+   */
+  function wrap(value, wrapper) {
+    return function() {
+      var args = [value];
+      push.apply(args, arguments);
+      return wrapper.apply(this, args);
+    };
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+   * corresponding HTML entities.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to escape.
+   * @returns {String} Returns the escaped string.
+   * @example
+   *
+   * _.escape('Moe, Larry & Curly');
+   * // => 'Moe, Larry &amp; Curly'
+   */
+  function escape(string) {
+    return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
+  }
+
+  /**
+   * This function returns the first argument passed to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Mixed} value Any value.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * var moe = { 'name': 'moe' };
+   * moe === _.identity(moe);
+   * // => true
+   */
+  function identity(value) {
+    return value;
+  }
+
+  /**
+   * Adds functions properties of `object` to the `lodash` function and chainable
+   * wrapper.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object of function properties to add to `lodash`.
+   * @example
+   *
+   * _.mixin({
+   *   'capitalize': function(string) {
+   *     return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+   *   }
+   * });
+   *
+   * _.capitalize('moe');
+   * // => 'Moe'
+   *
+   * _('moe').capitalize();
+   * // => 'Moe'
+   */
+  function mixin(object) {
+    forEach(functions(object), function(methodName) {
+      var func = lodash[methodName] = object[methodName];
+
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        return new lodash(func.apply(lodash, args));
+      };
+    });
+  }
+
+  /**
+   * Reverts the '_' variable to its previous value and returns a reference to
+   * the `lodash` function.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @returns {Function} Returns the `lodash` function.
+   * @example
+   *
+   * var lodash = _.noConflict();
+   */
+  function noConflict() {
+    window._ = oldDash;
+    return this;
+  }
+
+  /**
+   * Produces a random number between `min` and `max` (inclusive). If only one
+   * argument is passed, a number between `0` and the given number will be returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} [min=0] The minimum possible value.
+   * @param {Number} [max=1] The maximum possible value.
+   * @returns {Number} Returns a random number.
+   * @example
+   *
+   * _.random(0, 5);
+   * // => a number between 0 and 5
+   *
+   * _.random(5);
+   * // => also a number between 0 and 5
+   */
+  function random(min, max) {
+    if (min == null && max == null) {
+      max = 1;
+    }
+    min = +min || 0;
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + floor(nativeRandom() * ((+max || 0) - min + 1));
+  }
+
+  /**
+   * Resolves the value of `property` on `object`. If `property` is a function,
+   * it will be invoked and its result returned, else the property value is
+   * returned. If `object` is falsey, then `null` is returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object to inspect.
+   * @param {String} property The property to get the value of.
+   * @returns {Mixed} Returns the resolved value.
+   * @example
+   *
+   * var object = {
+   *   'cheese': 'crumpets',
+   *   'stuff': function() {
+   *     return 'nonsense';
+   *   }
+   * };
+   *
+   * _.result(object, 'cheese');
+   * // => 'crumpets'
+   *
+   * _.result(object, 'stuff');
+   * // => 'nonsense'
+   */
+  function result(object, property) {
+    var value = object ? object[property] : undefined;
+    return isFunction(value) ? object[property]() : value;
+  }
+
+  /**
+   * A micro-templating method that handles arbitrary delimiters, preserves
+   * whitespace, and correctly escapes quotes within interpolated code.
+   *
+   * Note: In the development build, `_.template` utilizes sourceURLs for easier
+   * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+   *
+   * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
+   * build and using precompiled templates, or loading Lo-Dash in a sandbox.
+   *
+   * For more information on precompiling templates see:
+   * http://lodash.com/#custom-builds
+   *
+   * For more information on Chrome extension sandboxes see:
+   * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} text The template text.
+   * @param {Obect} data The data object used to populate the text.
+   * @param {Object} options The options object.
+   *  escape - The "escape" delimiter regexp.
+   *  evaluate - The "evaluate" delimiter regexp.
+   *  interpolate - The "interpolate" delimiter regexp.
+   *  sourceURL - The sourceURL of the template's compiled source.
+   *  variable - The data object variable name.
+   *
+   * @returns {Function|String} Returns a compiled function when no `data` object
+   *  is given, else it returns the interpolated text.
+   * @example
+   *
+   * // using a compiled template
+   * var compiled = _.template('hello <%= name %>');
+   * compiled({ 'name': 'moe' });
+   * // => 'hello moe'
+   *
+   * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
+   * _.template(list, { 'people': ['moe', 'larry'] });
+   * // => '<li>moe</li><li>larry</li>'
+   *
+   * // using the "escape" delimiter to escape HTML in data property values
+   * _.template('<b><%- value %></b>', { 'value': '<script>' });
+   * // => '<b>&lt;script&gt;</b>'
+   *
+   * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+   * _.template('hello ${ name }', { 'name': 'curly' });
+   * // => 'hello curly'
+   *
+   * // using the internal `print` function in "evaluate" delimiters
+   * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
+   * // => 'hello stooge!'
+   *
+   * // using custom template delimiters
+   * _.templateSettings = {
+   *   'interpolate': /{{([\s\S]+?)}}/g
+   * };
+   *
+   * _.template('hello {{ name }}!', { 'name': 'mustache' });
+   * // => 'hello mustache!'
+   *
+   * // using the `sourceURL` option to specify a custom sourceURL for the template
+   * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+   * compiled(data);
+   * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+   *
+   * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+   * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+   * compiled.source;
+   * // => function(data) {
+   *   var __t, __p = '', __e = _.escape;
+   *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+   *   return __p;
+   * }
+   *
+   * // using the `source` property to inline compiled templates for meaningful
+   * // line numbers in error messages and a stack trace
+   * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+   *   var JST = {\
+   *     "main": ' + _.template(mainText).source + '\
+   *   };\
+   * ');
+   */
+  function template(text, data, options) {
+    // based on John Resig's `tmpl` implementation
+    // http://ejohn.org/blog/javascript-micro-templating/
+    // and Laura Doktorova's doT.js
+    // https://github.com/olado/doT
+    var settings = lodash.templateSettings;
+    text || (text = '');
+
+    // avoid missing dependencies when `iteratorTemplate` is not defined
+    options = defaults({}, options, settings);
+
+    var imports = defaults({}, options.imports, settings.imports),
+        importsKeys = keys(imports),
+        importsValues = values(imports);
+
+    var isEvaluating,
+        index = 0,
+        interpolate = options.interpolate || reNoMatch,
+        source = "__p += '";
+
+    // compile regexp to match each delimiter
+    var reDelimiters = RegExp(
+      (options.escape || reNoMatch).source + '|' +
+      interpolate.source + '|' +
+      (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+      (options.evaluate || reNoMatch).source + '|$'
+    , 'g');
+
+    text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+      interpolateValue || (interpolateValue = esTemplateValue);
+
+      // escape characters that cannot be included in string literals
+      source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+      // replace delimiters with snippets
+      if (escapeValue) {
+        source += "' +\n__e(" + escapeValue + ") +\n'";
+      }
+      if (evaluateValue) {
+        isEvaluating = true;
+        source += "';\n" + evaluateValue + ";\n__p += '";
+      }
+      if (interpolateValue) {
+        source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+      }
+      index = offset + match.length;
+
+      // the JS engine embedded in Adobe products requires returning the `match`
+      // string in order to produce the correct `offset` value
+      return match;
+    });
+
+    source += "';\n";
+
+    // if `variable` is not specified and the template contains "evaluate"
+    // delimiters, wrap a with-statement around the generated code to add the
+    // data object to the top of the scope chain
+    var variable = options.variable,
+        hasVariable = variable;
+
+    if (!hasVariable) {
+      variable = 'obj';
+      source = 'with (' + variable + ') {\n' + source + '\n}\n';
+    }
+    // cleanup code by stripping empty strings
+    source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+      .replace(reEmptyStringMiddle, '$1')
+      .replace(reEmptyStringTrailing, '$1;');
+
+    // frame code as the function body
+    source = 'function(' + variable + ') {\n' +
+      (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+      "var __t, __p = '', __e = _.escape" +
+      (isEvaluating
+        ? ', __j = Array.prototype.join;\n' +
+          "function print() { __p += __j.call(arguments, '') }\n"
+        : ';\n'
+      ) +
+      source +
+      'return __p\n}';
+
+    // Use a sourceURL for easier debugging and wrap in a multi-line comment to
+    // avoid issues with Narwhal, IE conditional compilation, and the JS engine
+    // embedded in Adobe products.
+    // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+    var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
+
+    try {
+      var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
+    } catch(e) {
+      e.source = source;
+      throw e;
+    }
+    if (data) {
+      return result(data);
+    }
+    // provide the compiled function's source via its `toString` method, in
+    // supported environments, or the `source` property as a convenience for
+    // inlining compiled templates during the build process
+    result.source = source;
+    return result;
+  }
+
+  /**
+   * Executes the `callback` function `n` times, returning an array of the results
+   * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
+   * with one argument; (index).
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} n The number of times to execute the callback.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+   * // => [3, 6, 4]
+   *
+   * _.times(3, function(n) { mage.castSpell(n); });
+   * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+   *
+   * _.times(3, function(n) { this.cast(n); }, mage);
+   * // => also calls `mage.castSpell(n)` three times
+   */
+  function times(n, callback, thisArg) {
+    n = +n || 0;
+    var index = -1,
+        result = Array(n);
+
+    while (++index < n) {
+      result[index] = callback.call(thisArg, index);
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.escape`, this method converts the HTML entities
+   * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+   * corresponding characters.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to unescape.
+   * @returns {String} Returns the unescaped string.
+   * @example
+   *
+   * _.unescape('Moe, Larry &amp; Curly');
+   * // => 'Moe, Larry & Curly'
+   */
+  function unescape(string) {
+    return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
+  }
+
+  /**
+   * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} [prefix] The value to prefix the ID with.
+   * @returns {String} Returns the unique ID.
+   * @example
+   *
+   * _.uniqueId('contact_');
+   * // => 'contact_104'
+   *
+   * _.uniqueId();
+   * // => '105'
+   */
+  function uniqueId(prefix) {
+    var id = ++idCounter;
+    return (prefix == null ? '' : prefix + '') + id;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Invokes `interceptor` with the `value` as the first argument, and then
+   * returns `value`. The purpose of this method is to "tap into" a method chain,
+   * in order to perform operations on intermediate results within the chain.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {Mixed} value The value to pass to `interceptor`.
+   * @param {Function} interceptor The function to invoke.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * _([1, 2, 3, 4])
+   *  .filter(function(num) { return num % 2 == 0; })
+   *  .tap(alert)
+   *  .map(function(num) { return num * num; })
+   *  .value();
+   * // => // [2, 4] (alerted)
+   * // => [4, 16]
+   */
+  function tap(value, interceptor) {
+    interceptor(value);
+    return value;
+  }
+
+  /**
+   * Produces the `toString` result of the wrapped value.
+   *
+   * @name toString
+   * @memberOf _
+   * @category Chaining
+   * @returns {String} Returns the string result.
+   * @example
+   *
+   * _([1, 2, 3]).toString();
+   * // => '1,2,3'
+   */
+  function wrapperToString() {
+    return this.__wrapped__ + '';
+  }
+
+  /**
+   * Extracts the wrapped value.
+   *
+   * @name valueOf
+   * @memberOf _
+   * @alias value
+   * @category Chaining
+   * @returns {Mixed} Returns the wrapped value.
+   * @example
+   *
+   * _([1, 2, 3]).valueOf();
+   * // => [1, 2, 3]
+   */
+  function wrapperValueOf() {
+    return this.__wrapped__;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return wrapped values when chaining
+  lodash.after = after;
+  lodash.assign = assign;
+  lodash.at = at;
+  lodash.bind = bind;
+  lodash.bindAll = bindAll;
+  lodash.bindKey = bindKey;
+  lodash.compact = compact;
+  lodash.compose = compose;
+  lodash.countBy = countBy;
+  lodash.debounce = debounce;
+  lodash.defaults = defaults;
+  lodash.defer = defer;
+  lodash.delay = delay;
+  lodash.difference = difference;
+  lodash.filter = filter;
+  lodash.flatten = flatten;
+  lodash.forEach = forEach;
+  lodash.forIn = forIn;
+  lodash.forOwn = forOwn;
+  lodash.functions = functions;
+  lodash.groupBy = groupBy;
+  lodash.initial = initial;
+  lodash.intersection = intersection;
+  lodash.invert = invert;
+  lodash.invoke = invoke;
+  lodash.keys = keys;
+  lodash.map = map;
+  lodash.max = max;
+  lodash.memoize = memoize;
+  lodash.merge = merge;
+  lodash.min = min;
+  lodash.object = object;
+  lodash.omit = omit;
+  lodash.once = once;
+  lodash.pairs = pairs;
+  lodash.partial = partial;
+  lodash.partialRight = partialRight;
+  lodash.pick = pick;
+  lodash.pluck = pluck;
+  lodash.range = range;
+  lodash.reject = reject;
+  lodash.rest = rest;
+  lodash.shuffle = shuffle;
+  lodash.sortBy = sortBy;
+  lodash.tap = tap;
+  lodash.throttle = throttle;
+  lodash.times = times;
+  lodash.toArray = toArray;
+  lodash.union = union;
+  lodash.uniq = uniq;
+  lodash.values = values;
+  lodash.where = where;
+  lodash.without = without;
+  lodash.wrap = wrap;
+  lodash.zip = zip;
+
+  // add aliases
+  lodash.collect = map;
+  lodash.drop = rest;
+  lodash.each = forEach;
+  lodash.extend = assign;
+  lodash.methods = functions;
+  lodash.select = filter;
+  lodash.tail = rest;
+  lodash.unique = uniq;
+
+  // add functions to `lodash.prototype`
+  mixin(lodash);
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return unwrapped values when chaining
+  lodash.clone = clone;
+  lodash.cloneDeep = cloneDeep;
+  lodash.contains = contains;
+  lodash.escape = escape;
+  lodash.every = every;
+  lodash.find = find;
+  lodash.has = has;
+  lodash.identity = identity;
+  lodash.indexOf = indexOf;
+  lodash.isArguments = isArguments;
+  lodash.isArray = isArray;
+  lodash.isBoolean = isBoolean;
+  lodash.isDate = isDate;
+  lodash.isElement = isElement;
+  lodash.isEmpty = isEmpty;
+  lodash.isEqual = isEqual;
+  lodash.isFinite = isFinite;
+  lodash.isFunction = isFunction;
+  lodash.isNaN = isNaN;
+  lodash.isNull = isNull;
+  lodash.isNumber = isNumber;
+  lodash.isObject = isObject;
+  lodash.isPlainObject = isPlainObject;
+  lodash.isRegExp = isRegExp;
+  lodash.isString = isString;
+  lodash.isUndefined = isUndefined;
+  lodash.lastIndexOf = lastIndexOf;
+  lodash.mixin = mixin;
+  lodash.noConflict = noConflict;
+  lodash.random = random;
+  lodash.reduce = reduce;
+  lodash.reduceRight = reduceRight;
+  lodash.result = result;
+  lodash.size = size;
+  lodash.some = some;
+  lodash.sortedIndex = sortedIndex;
+  lodash.template = template;
+  lodash.unescape = unescape;
+  lodash.uniqueId = uniqueId;
+
+  // add aliases
+  lodash.all = every;
+  lodash.any = some;
+  lodash.detect = find;
+  lodash.foldl = reduce;
+  lodash.foldr = reduceRight;
+  lodash.include = contains;
+  lodash.inject = reduce;
+
+  forOwn(lodash, function(func, methodName) {
+    if (!lodash.prototype[methodName]) {
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        return func.apply(lodash, args);
+      };
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions capable of returning wrapped and unwrapped values when chaining
+  lodash.first = first;
+  lodash.last = last;
+
+  // add aliases
+  lodash.take = first;
+  lodash.head = first;
+
+  forOwn(lodash, function(func, methodName) {
+    if (!lodash.prototype[methodName]) {
+      lodash.prototype[methodName]= function(callback, thisArg) {
+        var result = func(this.__wrapped__, callback, thisArg);
+        return callback == null || (thisArg && typeof callback != 'function')
+          ? result
+          : new lodash(result);
+      };
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The semantic version number.
+   *
+   * @static
+   * @memberOf _
+   * @type String
+   */
+  lodash.VERSION = '1.0.1';
+
+  // add "Chaining" functions to the wrapper
+  lodash.prototype.toString = wrapperToString;
+  lodash.prototype.value = wrapperValueOf;
+  lodash.prototype.valueOf = wrapperValueOf;
+
+  // add `Array` functions that return unwrapped values
+  each(['join', 'pop', 'shift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      return func.apply(this.__wrapped__, arguments);
+    };
+  });
+
+  // add `Array` functions that return the wrapped value
+  each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      func.apply(this.__wrapped__, arguments);
+      return this;
+    };
+  });
+
+  // add `Array` functions that return new wrapped values
+  each(['concat', 'slice', 'splice'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      return new lodash(func.apply(this.__wrapped__, arguments));
+    };
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Lo-Dash
+  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash was injected by a third-party script and not intended to be
+    // loaded as a module. The global assignment can be reverted in the Lo-Dash
+    // module via its `noConflict()` method.
+    window._ = lodash;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return lodash;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports) {
+    // in Node.js or RingoJS v0.8.0+
+    if (freeModule) {
+      (freeModule.exports = lodash)._ = lodash;
+    }
+    // in Narwhal or RingoJS v0.7.0-
+    else {
+      freeExports._ = lodash;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    window._ = lodash;
+  }
+}(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.min.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.min.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.min.js	(revision 533)
@@ -0,0 +1,40 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 (Custom Build) lodash.com/license
+ * Build: `lodash modern -o ./dist/lodash.js`
+ * Underscore.js 1.4.4 underscorejs.org/LICENSE
+ */
+;(function(n,t){function r(n){if(!n||typeof n!="object")return W;var t=n.valueOf,r=typeof t=="function"&&(r=bt(t))&&bt(r);if(r)n=n==r||bt(n)==r&&!h(n);else{var e=W;!n||typeof n!="object"||h(n)?n=e:(t=n.constructor,!j(t)||t instanceof t?(Yt(n,function(n,t){e=t}),n=e===W||jt.call(n,e)):n=e)}return n}function e(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof e?(this.__wrapped__=n,void 0):new e(n)}function u(n,t,r){t||(t=0);var e=n.length,u=e-t>=(r||ut);if(u){var o={};for(r=t-1;++r<e;){var i=n[r]+"";
+(jt.call(o,i)?o[i]:o[i]=[]).push(n[r])}}return function(r){if(u){var e=r+"";return jt.call(o,e)&&-1<z(o[e],r)}return-1<z(n,r,t)}}function o(n){return n.charCodeAt(0)}function i(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1}return r<e?-1:1}function f(n,t,r,e){function u(){var a=arguments,c=i?this:t;return o||(n=t[f]),r.length&&(a=a.length?(a=v(a),e?a.concat(r):r.concat(a)):r),this instanceof u?(s.prototype=n.prototype,c=new s,s.prototype=Q,a=n.apply(c,a),w(a)?a:c):n.apply(c,a)
+}var o=j(n),i=!r,f=t;return i&&(r=t),o||(t=n),u}function a(n,t,r){if(n==Q)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=tr(n);return function(t){for(var r=u.length,e=W;r--&&(e=b(t[u[r]],n[u[r]],et)););return e}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function c(){for(var n,t={g:Ut,b:"l(n)",c:"",h:"",l:"",m:L},r=0;n=arguments[r];r++)for(var e in n)t[e]=n[e];
+return n=t.a,t.d=/^[^,]+/.exec(n)[0],r="var j,n="+t.d+",u=n;if(!n)return u;"+t.l+";",t.b&&(r+="var o=n.length;j=-1;if("+t.b+"){while(++j<o){"+t.h+"}}else{"),t.g&&t.m?r+="var s=-1,t=r[typeof n]?p(n):[],o=t.length;while(++s<o){j=t[s];"+t.h+"}":(r+="for(j in n){",t.m&&(r+="if(",t.m&&(r+="i.call(n,j)"),r+="){"),r+=t.h+";",t.m&&(r+="}"),r+="}"),t.b&&(r+="}"),r+=t.c+";return u",Function("f,i,k,l,m,r,p","return function("+n+"){"+r+"}")(a,jt,h,nr,A,Ht,kt)}function l(n){return"\\"+Jt[n]}function p(n){return rr[n]
+}function s(){}function v(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function g(n){return er[n]}function h(n){return xt.call(n)==Ft}function y(n){var t=[];return Zt(n,function(n,r){t.push(r)}),t}function m(n,r,e,u,o,i){var f=n;if(typeof r=="function"&&(u=e,e=r,r=W),typeof e=="function"){e=typeof u=="undefined"?e:a(e,u,1);var f=e(f),c=typeof f!="undefined";c||(f=n)}if(u=w(f)){var l=xt.call(f);if(!Vt[l])return f;var p=nr(f)
+}if(!u||!r)return u&&!c?p?v(f):ur({},f):f;switch(u=Gt[l],l){case Dt:case It:return c?f:new u(+f);case Tt:case zt:return c?f:new u(f);case Mt:return c?f:u(f.source,lt.exec(f))}for(o||(o=[]),i||(i=[]),l=o.length;l--;)if(o[l]==n)return i[l];return c||(f=p?u(f.length):{},p&&(jt.call(n,"index")&&(f.index=n.index),jt.call(n,"input")&&(f.input=n.input))),o.push(n),i.push(f),(p?$:Zt)(c?f:n,function(n,u){f[u]=m(n,r,e,t,o,i)}),f}function d(n){var t=[];return Yt(n,function(n,r){j(n)&&t.push(r)}),t.sort()}function _(n){for(var t=-1,r=tr(n),e=r.length,u={};++t<e;){var o=r[t];
+u[n[o]]=o}return u}function b(n,t,r,e,u,o){var i=r===et;if(r&&!i){r=typeof e=="undefined"?r:a(r,e,2);var f=r(n,t);if(typeof f!="undefined")return!!f}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,l=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=l&&"object"!=l))return W;if(n==Q||t==Q)return n===t;if(l=xt.call(n),c=xt.call(t),l==Ft&&(l=Bt),c==Ft&&(c=Bt),l!=c)return W;switch(l){case Dt:case It:return+n==+t;case Tt:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Mt:case zt:return n==t+""
+}if(c=l==qt,!c){if(n.__wrapped__||t.__wrapped__)return b(n.__wrapped__||n,t.__wrapped__||t,r,e,u,o);if(l!=Bt)return W;var l=n.constructor,p=t.constructor;if(l!=p&&(!j(l)||!(l instanceof l&&j(p)&&p instanceof p)))return W}for(u||(u=[]),o||(o=[]),l=u.length;l--;)if(u[l]==n)return o[l]==t;var s=0,f=L;if(u.push(n),o.push(t),c){if(l=n.length,s=t.length,f=s==n.length,!f&&!i)return f;for(;s--;)if(c=l,p=t[s],i)for(;c--&&!(f=b(n[c],p,r,e,u,o)););else if(!(f=b(n[s],p,r,e,u,o)))break;return f}return Yt(t,function(t,i,a){return jt.call(a,i)?(s++,f=jt.call(n,i)&&b(n[i],t,r,e,u,o)):void 0
+}),f&&!i&&Yt(n,function(n,t,r){return jt.call(r,t)?f=-1<--s:void 0}),f}function j(n){return typeof n=="function"}function w(n){return n?Ht[typeof n]:W}function x(n){return typeof n=="number"||xt.call(n)==Tt}function A(n){return typeof n=="string"||xt.call(n)==zt}function O(n,t,e){var u=arguments,o=0,i=2;if(!w(n))return n;if(e===et)var f=u[3],c=u[4],l=u[5];else c=[],l=[],typeof e!="number"&&(i=u.length),3<i&&"function"==typeof u[i-2]?f=a(u[--i-1],u[i--],2):2<i&&"function"==typeof u[i-1]&&(f=u[--i]);for(;++o<i;)(nr(u[o])?$:Zt)(u[o],function(t,e){var u,o,i=t,a=n[e];
+if(t&&((o=nr(t))||r(t))){for(i=c.length;i--;)if(u=c[i]==t){a=l[i];break}u||(a=o?nr(a)?a:[]:r(a)?a:{},f&&(i=f(a,t),typeof i!="undefined"&&(a=i)),c.push(t),l.push(a),f||(a=O(a,t,et,f,c,l)))}else f&&(i=f(a,t),typeof i=="undefined"&&(i=t)),typeof i!="undefined"&&(a=i);n[e]=a});return n}function E(n){for(var t=-1,r=tr(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function S(n,t,r){var e=-1,u=n?n.length:0,o=W;return r=(0>r?Nt(0,u+r):r)||0,typeof u=="number"?o=-1<(A(n)?n.indexOf(t,r):z(n,t,r)):Xt(n,function(n){return++e<r?void 0:!(o=n===t)
+}),o}function k(n,t,r){var e=L;if(t=a(t,r),nr(n)){r=-1;for(var u=n.length;++r<u&&(e=!!t(n[r],r,n)););}else Xt(n,function(n,r,u){return e=!!t(n,r,u)});return e}function N(n,t,r){var e=[];if(t=a(t,r),nr(n)){r=-1;for(var u=n.length;++r<u;){var o=n[r];t(o,r,n)&&e.push(o)}}else Xt(n,function(n,r,u){t(n,r,u)&&e.push(n)});return e}function R(n,t,r){var e;return t=a(t,r),$(n,function(n,r,u){return t(n,r,u)?(e=n,W):void 0}),e}function $(n,t,r){if(t&&typeof r=="undefined"&&nr(n)){r=-1;for(var e=n.length;++r<e&&t(n[r],r,n)!==W;);}else Xt(n,t,r);
+return n}function F(n,t,r){var e=-1,u=n?n.length:0,o=Array(typeof u=="number"?u:0);if(t=a(t,r),nr(n))for(;++e<u;)o[e]=t(n[e],e,n);else Xt(n,function(n,r,u){o[++e]=t(n,r,u)});return o}function q(n,t,r){var e=-1/0,u=e;if(!t&&nr(n)){r=-1;for(var i=n.length;++r<i;){var f=n[r];f>u&&(u=f)}}else t=!t&&A(n)?o:a(t,r),Xt(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});return u}function D(n,t,r,e){var u=3>arguments.length;if(t=a(t,e,4),nr(n)){var o=-1,i=n.length;for(u&&(r=n[++o]);++o<i;)r=t(r,n[o],o,n)}else Xt(n,function(n,e,o){r=u?(u=W,n):t(r,n,e,o)
+});return r}function I(n,t,r,e){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=tr(n),u=i.length;return t=a(t,e,4),$(n,function(e,f,a){f=i?i[--u]:--u,r=o?(o=W,n[f]):t(r,n[f],f,a)}),r}function T(n,t,r){var e;if(t=a(t,r),nr(n)){r=-1;for(var u=n.length;++r<u&&!(e=t(n[r],r,n)););}else Xt(n,function(n,r,u){return!(e=t(n,r,u))});return!!e}function B(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=Q){var o=-1;for(t=a(t,r);++o<u&&t(n[o],o,n);)e++}else if(e=t,e==Q||r)return n[0];
+return v(n,0,Rt(Nt(0,e),u))}}function M(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];nr(o)?wt.apply(u,t?o:M(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;if(typeof r=="number")e=(0>r?Nt(0,u+r):r||0)-1;else if(r)return e=C(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function P(n,t,r){if(typeof t!="number"&&t!=Q){var e=0,u=-1,o=n?n.length:0;for(t=a(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==Q||r?1:Nt(0,t);return v(n,e)}function C(n,t,r,e){var u=0,o=n?n.length:u;
+for(r=r?a(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function K(n,t,r,e){var u=-1,o=n?n.length:0,i=[],f=i;typeof t=="function"&&(e=r,r=t,t=W);var c=!t&&75<=o;if(c)var l={};for(r&&(f=[],r=a(r,e));++u<o;){e=n[u];var p=r?r(e,u,n):e;if(c)var s=p+"",s=jt.call(l,s)?!(f=l[s]):f=l[s]=[];(t?!u||f[f.length-1]!==p:s||0>z(f,p))&&((r||c)&&f.push(p),i.push(e))}return i}function U(n,t){return Kt||At&&2<arguments.length?At.call.apply(At,arguments):f(n,t,v(arguments,2))}function V(n){var r=v(arguments,1);
+return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){$(d(n),function(t){var r=e[t]=n[t];e.prototype[t]=function(){var n=[this.__wrapped__];return wt.apply(n,arguments),new e(r.apply(e,n))}})}function J(){return this.__wrapped__}var L=!0,Q=null,W=!1,X=typeof exports=="object"&&exports,Y=typeof module=="object"&&module&&module.exports==X&&module,Z=typeof global=="object"&&global;Z.global===Z&&(n=Z);var nt=[],tt={},rt=0,et=tt,ut=30,ot=n._,it=/&(?:amp|lt|gt|quot|#39);/g,ft=/\b__p\+='';/g,at=/\b(__p\+=)''\+/g,ct=/(__e\(.*?\)|\b__t\))\+'';/g,lt=/\w*$/,pt=RegExp("^"+(tt.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),st=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,vt=/<%=([\s\S]+?)%>/g,gt=/($^)/,ht=/[&<>"']/g,yt=/['\n\r\t\u2028\u2029\\]/g,mt=Math.ceil,dt=nt.concat,_t=Math.floor,bt=pt.test(bt=Object.getPrototypeOf)&&bt,jt=tt.hasOwnProperty,wt=nt.push,xt=tt.toString,At=pt.test(At=v.bind)&&At,Ot=pt.test(Ot=Array.isArray)&&Ot,Et=n.isFinite,St=n.isNaN,kt=pt.test(kt=Object.keys)&&kt,Nt=Math.max,Rt=Math.min,$t=Math.random,Ft="[object Arguments]",qt="[object Array]",Dt="[object Boolean]",It="[object Date]",Tt="[object Number]",Bt="[object Object]",Mt="[object RegExp]",zt="[object String]",Pt=!!n.attachEvent,Ct=At&&!/\n|true/.test(At+Pt),Kt=At&&!Ct,Ut=kt&&(Pt||Ct),Vt={"[object Function]":W};
+Vt[Ft]=Vt[qt]=Vt[Dt]=Vt[It]=Vt[Tt]=Vt[Bt]=Vt[Mt]=Vt[zt]=L;var Gt={};Gt[qt]=Array,Gt[Dt]=Boolean,Gt[It]=Date,Gt[Bt]=Object,Gt[Tt]=Number,Gt[Mt]=RegExp,Gt[zt]=String;var Ht={"boolean":W,"function":L,object:L,number:W,string:W,undefined:W},Jt={"\\":"\\","'":"'","\n":"n","\r":"r","	":"t","\u2028":"u2028","\u2029":"u2029"};e.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:vt,variable:"",imports:{_:e}};var Lt={a:"q,w,h",l:"var a=arguments,b=0,c=typeof h=='number'?2:a.length;while(++b<c){n=a[b];if(n&&r[typeof n]){",h:"if(typeof u[j]=='undefined')u[j]=n[j]",c:"}}"},Qt={a:"e,d,x",l:"d=d&&typeof x=='undefined'?d:f(d,x)",b:"typeof o=='number'",h:"if(d(n[j],j,e)===false)return u"},Wt={l:"if(!r[typeof n])return u;"+Qt.l,b:W},Xt=c(Qt),Yt=c(Qt,Wt,{m:W}),Zt=c(Qt,Wt),nr=Ot||function(n){return n instanceof Array||xt.call(n)==qt
+},tr=kt?function(n){return w(n)?kt(n):[]}:y,rr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},er=_(rr),ur=c(Lt,{l:Lt.l.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=f(a[--c-1],a[c--],2);}else if(c>2&&typeof a[c-1]=='function'){d=a[--c];}"),h:"u[j]=d?d(u[j],n[j]):n[j]"}),or=c(Lt);j(/x/)&&(j=function(n){return n instanceof Function||"[object Function]"==xt.call(n)}),Ct&&Y&&typeof setImmediate=="function"&&(V=U(setImmediate,n)),e.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0
+}},e.assign=ur,e.at=function(n){for(var t=-1,r=dt.apply(nt,v(arguments,1)),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u},e.bind=U,e.bindAll=function(n){for(var t=dt.apply(nt,arguments),r=1<t.length?0:(t=d(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=U(n[u],n)}return n},e.bindKey=function(n,t){return f(n,t,v(arguments,2))},e.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},e.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];
+return t[0]}},e.countBy=function(n,t,r){var e={};return t=a(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",jt.call(e,r)?e[r]++:e[r]=1}),e},e.debounce=function(n,t,r){function e(){f=Q,r||(o=n.apply(i,u))}var u,o,i,f;return function(){var a=r&&!f;return u=arguments,i=this,clearTimeout(f),f=setTimeout(e,t),a&&(o=n.apply(i,u)),o}},e.defaults=or,e.defer=V,e.delay=function(n,r){var e=v(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},e.difference=function(n){for(var t=-1,r=n?n.length:0,e=dt.apply(nt,arguments),e=u(e,r),o=[];++t<r;){var i=n[t];
+e(i)||o.push(i)}return o},e.filter=N,e.flatten=M,e.forEach=$,e.forIn=Yt,e.forOwn=Zt,e.functions=d,e.groupBy=function(n,t,r){var e={};return t=a(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",(jt.call(e,r)?e[r]:e[r]=[]).push(n)}),e},e.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=Q){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else e=t==Q||r?1:t||e;return v(n,0,Rt(Nt(0,u-e),u))},e.intersection=function(n){var t=arguments,r=t.length,e={0:{}},o=-1,i=n?n.length:0,f=100<=i,a=[],c=a;
+n:for(;++o<i;){var l=n[o];if(f)var p=l+"",p=jt.call(e[0],p)?!(c=e[0][p]):c=e[0][p]=[];if(p||0>z(c,l)){f&&c.push(l);for(var s=r;--s;)if(!(e[s]||(e[s]=u(t[s],0,100)))(l))continue n;a.push(l)}}return a},e.invert=_,e.invoke=function(n,t){var r=v(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);return $(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},e.keys=tr,e.map=F,e.max=q,e.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";
+return jt.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},e.merge=O,e.min=function(n,t,r){var e=1/0,u=e;if(!t&&nr(n)){r=-1;for(var i=n.length;++r<i;){var f=n[r];f<u&&(u=f)}}else t=!t&&A(n)?o:a(t,r),Xt(n,function(n,r,o){r=t(n,r,o),r<e&&(e=r,u=n)});return u},e.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]}return u},e.omit=function(n,t,r){var e=typeof t=="function",u={};if(e)t=a(t,r);else var o=dt.apply(nt,arguments);return Yt(n,function(n,r,i){(e?!t(n,r,i):0>z(o,r,1))&&(u[r]=n)
+}),u},e.once=function(n){var t,r;return function(){return t?r:(t=L,r=n.apply(this,arguments),n=Q,r)}},e.pairs=function(n){for(var t=-1,r=tr(n),e=r.length,u=Array(e);++t<e;){var o=r[t];u[t]=[o,n[o]]}return u},e.partial=function(n){return f(n,v(arguments,1))},e.partialRight=function(n){return f(n,v(arguments,1),Q,et)},e.pick=function(n,t,r){var e={};if(typeof t!="function")for(var u=0,o=dt.apply(nt,arguments),i=w(n)?o.length:0;++u<i;){var f=o[u];f in n&&(e[f]=n[f])}else t=a(t,r),Yt(n,function(n,r,u){t(n,r,u)&&(e[r]=n)
+});return e},e.pluck=F,e.range=function(n,t,r){n=+n||0,r=+r||1,t==Q&&(t=n,n=0);var e=-1;t=Nt(0,mt((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},e.reject=function(n,t,r){return t=a(t,r),N(n,function(n,r,e){return!t(n,r,e)})},e.rest=P,e.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r=_t($t()*(++t+1));e[t]=e[r],e[r]=n}),e},e.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,o=Array(typeof u=="number"?u:0);for(t=a(t,r),$(n,function(n,r,u){o[++e]={a:t(n,r,u),b:e,c:n}
+}),u=o.length,o.sort(i);u--;)o[u]=o[u].c;return o},e.tap=function(n,t){return t(n),n},e.throttle=function(n,t){function r(){f=new Date,i=Q,u=n.apply(o,e)}var e,u,o,i,f=0;return function(){var a=new Date,c=t-(a-f);return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=Q,f=a,u=n.apply(o,e)),u}},e.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},e.toArray=function(n){return n&&typeof n.length=="number"?v(n):E(n)},e.union=function(){return K(dt.apply(nt,arguments))
+},e.uniq=K,e.values=E,e.where=N,e.without=function(n){for(var t=-1,r=n?n.length:0,e=u(arguments,1),o=[];++t<r;){var i=n[t];e(i)||o.push(i)}return o},e.wrap=function(n,t){return function(){var r=[n];return wt.apply(r,arguments),t.apply(this,r)}},e.zip=function(n){for(var t=-1,r=n?q(F(arguments,"length")):0,e=Array(r);++t<r;)e[t]=F(arguments,t);return e},e.collect=F,e.drop=P,e.each=$,e.extend=ur,e.methods=d,e.select=N,e.tail=P,e.unique=K,H(e),e.clone=m,e.cloneDeep=function(n,t,r){return m(n,L,t,r)},e.contains=S,e.escape=function(n){return n==Q?"":(n+"").replace(ht,p)
+},e.every=k,e.find=R,e.has=function(n,t){return n?jt.call(n,t):W},e.identity=G,e.indexOf=z,e.isArguments=h,e.isArray=nr,e.isBoolean=function(n){return n===L||n===W||xt.call(n)==Dt},e.isDate=function(n){return n instanceof Date||xt.call(n)==It},e.isElement=function(n){return n?1===n.nodeType:W},e.isEmpty=function(n){var t=L;if(!n)return t;var r=xt.call(n),e=n.length;return r==qt||r==zt||r==Ft||r==Bt&&typeof e=="number"&&j(n.splice)?!e:(Zt(n,function(){return t=W}),t)},e.isEqual=b,e.isFinite=function(n){return Et(n)&&!St(parseFloat(n))
+},e.isFunction=j,e.isNaN=function(n){return x(n)&&n!=+n},e.isNull=function(n){return n===Q},e.isNumber=x,e.isObject=w,e.isPlainObject=r,e.isRegExp=function(n){return n instanceof RegExp||xt.call(n)==Mt},e.isString=A,e.isUndefined=function(n){return typeof n=="undefined"},e.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?Nt(0,e+r):Rt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},e.mixin=H,e.noConflict=function(){return n._=ot,this},e.random=function(n,t){return n==Q&&t==Q&&(t=1),n=+n||0,t==Q&&(t=n,n=0),n+_t($t()*((+t||0)-n+1))
+},e.reduce=D,e.reduceRight=I,e.result=function(n,r){var e=n?n[r]:t;return j(e)?n[r]():e},e.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:tr(n).length},e.some=T,e.sortedIndex=C,e.template=function(n,r,u){var o=e.templateSettings;n||(n=""),u=or({},u,o);var i,f=or({},u.imports,o.imports),o=tr(f),f=E(f),a=0,c=u.interpolate||gt,p="__p+='";n.replace(RegExp((u.escape||gt).source+"|"+c.source+"|"+(c===vt?st:gt).source+"|"+(u.evaluate||gt).source+"|$","g"),function(t,r,e,u,o,f){return e||(e=u),p+=n.slice(a,f).replace(yt,l),r&&(p+="'+__e("+r+")+'"),o&&(i=L,p+="';"+o+";__p+='"),e&&(p+="'+((__t=("+e+"))==null?'':__t)+'"),a=f+t.length,t
+}),p+="';\n",c=u=u.variable,c||(u="obj",p="with("+u+"){"+p+"}"),p=(i?p.replace(ft,""):p).replace(at,"$1").replace(ct,"$1;"),p="function("+u+"){"+(c?"":u+"||("+u+"={});")+"var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+p+"return __p}";try{var s=Function(o,"return "+p).apply(t,f)}catch(v){throw v.source=p,v}return r?s(r):(s.source=p,s)},e.unescape=function(n){return n==Q?"":(n+"").replace(it,g)},e.uniqueId=function(n){var t=++rt;return(n==Q?"":n+"")+t
+},e.all=k,e.any=T,e.detect=R,e.foldl=D,e.foldr=I,e.include=S,e.inject=D,Zt(e,function(n,t){e.prototype[t]||(e.prototype[t]=function(){var t=[this.__wrapped__];return wt.apply(t,arguments),n.apply(e,t)})}),e.first=B,e.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=Q){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==Q||r)return n[u-1];return v(n,Nt(0,u-e))}},e.take=B,e.head=B,Zt(e,function(n,t){e.prototype[t]||(e.prototype[t]=function(t,r){var u=n(this.__wrapped__,t,r);
+return t==Q||r&&typeof t!="function"?u:new e(u)})}),e.VERSION="1.0.1",e.prototype.toString=function(){return this.__wrapped__+""},e.prototype.value=J,e.prototype.valueOf=J,Xt(["join","pop","shift"],function(n){var t=nt[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)}}),Xt(["push","reverse","sort","unshift"],function(n){var t=nt[n];e.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Xt(["concat","slice","splice"],function(n){var t=nt[n];e.prototype[n]=function(){return new e(t.apply(this.__wrapped__,arguments))
+}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=e,define(function(){return e})):X?Y?(Y.exports=e)._=e:X._=e:n._=e})(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.underscore.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.underscore.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.underscore.js	(revision 533)
@@ -0,0 +1,4307 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 (Custom Build) <http://lodash.com/>
+ * Build: `lodash underscore -o ./dist/lodash.underscore.js`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function(window, undefined) {
+
+  /** Detect free variable `exports` */
+  var freeExports = typeof exports == 'object' && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
+
+  /** Detect free variable `global` and use it as `window` */
+  var freeGlobal = typeof global == 'object' && global;
+  if (freeGlobal.global === freeGlobal) {
+    window = freeGlobal;
+  }
+
+  /** Used for array and object method references */
+  var arrayRef = [],
+      objectRef = {};
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = objectRef;
+
+  /** Used to restore the original `_` reference in `noConflict` */
+  var oldDash = window._;
+
+  /** Used to match HTML entities */
+  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detect if a method is native */
+  var reNative = RegExp('^' +
+    (objectRef.valueOf + '')
+      .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+      .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
+  );
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to match HTML characters */
+  var reUnescapedHtml = /[&<>"']/g;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** Native method shortcuts */
+  var ceil = Math.ceil,
+      concat = arrayRef.concat,
+      floor = Math.floor,
+      hasOwnProperty = objectRef.hasOwnProperty,
+      push = arrayRef.push,
+      toString = objectRef.toString;
+
+  /* Native method shortcuts for methods with the same name as other `lodash` methods */
+  var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
+      nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
+      nativeIsFinite = window.isFinite,
+      nativeIsNaN = window.isNaN,
+      nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+      nativeMax = Math.max,
+      nativeMin = Math.min,
+      nativeRandom = Math.random;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Detect various environments */
+  var isIeOpera = !!window.attachEvent,
+      isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
+
+  /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
+  var isBindFast = nativeBind && !isV8;
+
+  /**
+   * Detect if `Array#shift` and `Array#splice` augment array-like objects
+   * incorrectly:
+   *
+   * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+   * and `splice()` functions that fail to remove the last element, `value[0]`,
+   * of array-like objects even though the `length` property is set to `0`.
+   * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+   * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+   */
+  var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
+    arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
+
+  /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */
+  var argsAreObjects = arguments.constructor == Object;
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object, that wraps the given `value`, to enable method
+   * chaining.
+   *
+   * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+   * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+   * and `unshift`
+   *
+   * The chainable wrapper functions are:
+   * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
+   * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
+   * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
+   * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
+   * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+   * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
+   * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
+   * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
+   *
+   * The non-chainable wrapper functions are:
+   * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
+   * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
+   * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
+   * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
+   * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
+   * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
+   *
+   * The wrapper functions `first` and `last` return wrapped values when `n` is
+   * passed, otherwise they return unwrapped values.
+   *
+   * @name _
+   * @constructor
+   * @category Chaining
+   * @param {Mixed} value The value to wrap in a `lodash` instance.
+   * @returns {Object} Returns a `lodash` instance.
+   */
+  function lodash(value) {
+    // exit early if already wrapped, even if wrapped by a different `lodash` constructor
+    if (value && typeof value == 'object' && value.__wrapped__) {
+      return value;
+    }
+    // allow invoking `lodash` without the `new` operator
+    if (!(this instanceof lodash)) {
+      return new lodash(value);
+    }
+    this.__wrapped__ = value;
+  }
+
+  /**
+   * By default, the template delimiters used by Lo-Dash are similar to those in
+   * embedded Ruby (ERB). Change the following template settings to use alternative
+   * delimiters.
+   *
+   * @static
+   * @memberOf _
+   * @type Object
+   */
+  lodash.templateSettings = {
+
+    /**
+     * Used to detect `data` property values to be HTML-escaped.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'escape': /<%-([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect code to be evaluated.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'evaluate': /<%([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect `data` property values to inject.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'interpolate': reInterpolate,
+
+    /**
+     * Used to reference the data object in the template text.
+     *
+     * @memberOf _.templateSettings
+     * @type String
+     */
+    'variable': ''
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Used by `_.max` and `_.min` as the default `callback` when a given
+   * `collection` is a string value.
+   *
+   * @private
+   * @param {String} value The character to inspect.
+   * @returns {Number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` values, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {Number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ai = a.index,
+        bi = b.index;
+
+    a = a.criteria;
+    b = b.criteria;
+
+    // ensure a stable sort in V8 and other engines
+    // http://code.google.com/p/v8/issues/detail?id=90
+    if (a !== b) {
+      if (a > b || typeof a == 'undefined') {
+        return 1;
+      }
+      if (a < b || typeof b == 'undefined') {
+        return -1;
+      }
+    }
+    return ai < bi ? -1 : 1;
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this` binding
+   * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
+   * bound function.
+   *
+   * @private
+   * @param {Function|String} func The function to bind or the method name.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Array} partialArgs An array of arguments to be partially applied.
+   * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
+   * @returns {Function} Returns the new bound function.
+   */
+  function createBound(func, thisArg, partialArgs, rightIndicator) {
+    var isFunc = isFunction(func),
+        isPartial = !partialArgs,
+        key = thisArg;
+
+    // juggle arguments
+    if (isPartial) {
+      partialArgs = thisArg;
+    }
+    if (!isFunc) {
+      thisArg = func;
+    }
+
+    function bound() {
+      // `Function#bind` spec
+      // http://es5.github.com/#x15.3.4.5
+      var args = arguments,
+          thisBinding = isPartial ? this : thisArg;
+
+      if (!isFunc) {
+        func = thisArg[key];
+      }
+      if (partialArgs.length) {
+        args = args.length
+          ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
+          : partialArgs;
+      }
+      if (this instanceof bound) {
+        // ensure `new bound` is an instance of `bound` and `func`
+        noop.prototype = func.prototype;
+        thisBinding = new noop;
+        noop.prototype = null;
+
+        // mimic the constructor's `return` behavior
+        // http://es5.github.com/#x13.2.2
+        var result = func.apply(thisBinding, args);
+        return isObject(result) ? result : thisBinding;
+      }
+      return func.apply(thisBinding, args);
+    }
+    return bound;
+  }
+
+  /**
+   * Produces a callback bound to an optional `thisArg`. If `func` is a property
+   * name, the created callback will return the property value for a given element.
+   * If `func` is an object, the created callback will return `true` for elements
+   * that contain the equivalent object properties, otherwise it will return `false`.
+   *
+   * @private
+   * @param {Mixed} [func=identity] The value to convert to a callback.
+   * @param {Mixed} [thisArg] The `this` binding of the created callback.
+   * @param {Number} [argCount=3] The number of arguments the callback accepts.
+   * @returns {Function} Returns a callback function.
+   */
+  function createCallback(func, thisArg, argCount) {
+    if (func == null) {
+      return identity;
+    }
+    var type = typeof func;
+    if (type != 'function') {
+      if (type != 'object') {
+        return function(object) {
+          return object[func];
+        };
+      }
+      var props = keys(func);
+      return function(object) {
+        var length = props.length,
+            result = false;
+        while (length--) {
+          if (!(result = object[props[length]] === func[props[length]])) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+    if (typeof thisArg != 'undefined') {
+      if (argCount === 1) {
+        return function(value) {
+          return func.call(thisArg, value);
+        };
+      }
+      if (argCount === 2) {
+        return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+      }
+      if (argCount === 4) {
+        return function(accumulator, value, index, object) {
+          return func.call(thisArg, accumulator, value, index, object);
+        };
+      }
+      return function(value, index, object) {
+        return func.call(thisArg, value, index, object);
+      };
+    }
+    return func;
+  }
+
+  /**
+   * A function compiled to iterate `arguments` objects, arrays, objects, and
+   * strings consistenly across environments, executing the `callback` for each
+   * element in the `collection`. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, index|key, collection). Callbacks may exit
+   * iteration early by explicitly returning `false`.
+   *
+   * @private
+   * @type Function
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   */
+  var each = function (collection, callback, thisArg) {
+    var index, iterable = collection, result = iterable;
+    if (!iterable) return result;
+    callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg);
+    var length = iterable.length; index = -1;
+    if (typeof length == 'number') {
+      while (++index < length) {
+        if (callback(iterable[index], index, collection) === indicatorObject) return result
+      }
+    }
+    else {  
+      for (index in iterable) {
+        if (hasOwnProperty.call(iterable, index)) {    
+        if (callback(iterable[index], index, collection) === indicatorObject) return result;    
+        }
+      }  
+    }
+  };
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Used by `escape` to convert characters to HTML entities.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeHtmlChar(match) {
+    return htmlEscapes[match];
+  }
+
+  /**
+   * Checks if `value` is a DOM node in IE < 9.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
+   */
+  function isNode(value) {
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings
+    return typeof value.toString != 'function' && typeof (value + '') == 'string';
+  }
+
+  /**
+   * A no-operation function.
+   *
+   * @private
+   */
+  function noop() {
+    // no operation performed
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used, instead of `Array#slice`, to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|String} collection The collection to slice.
+   * @param {Number} start The start index.
+   * @param {Number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /**
+   * Used by `unescape` to convert HTML entities to characters.
+   *
+   * @private
+   * @param {String} match The matched character to unescape.
+   * @returns {String} Returns the unescaped character.
+   */
+  function unescapeHtmlChar(match) {
+    return htmlUnescapes[match];
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if `value` is an `arguments` object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
+   * @example
+   *
+   * (function() { return _.isArguments(arguments); })(1, 2, 3);
+   * // => true
+   *
+   * _.isArguments([1, 2, 3]);
+   * // => false
+   */
+  function isArguments(value) {
+    return toString.call(value) == argsClass;
+  }
+  // fallback for browsers that can't detect `arguments` objects by [[Class]]
+  if (!isArguments(arguments)) {
+    isArguments = function(value) {
+      return value ? hasOwnProperty.call(value, 'callee') : false;
+    };
+  }
+
+  /**
+   * Iterates over `object`'s own and inherited enumerable properties, executing
+   * the `callback` for each property. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, key, object). Callbacks may exit iteration
+   * early by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * function Dog(name) {
+   *   this.name = name;
+   * }
+   *
+   * Dog.prototype.bark = function() {
+   *   alert('Woof, woof!');
+   * };
+   *
+   * _.forIn(new Dog('Dagny'), function(value, key) {
+   *   alert(key);
+   * });
+   * // => alerts 'name' and 'bark' (order is not guaranteed)
+   */
+  var forIn = function (collection, callback) {
+    var index, iterable = collection, result = iterable;
+    if (!iterable) return result;
+    if (!objectTypes[typeof iterable]) return result;
+    callback || (callback = identity);
+    
+      for (index in iterable) {
+        if (callback(iterable[index], index, collection) === indicatorObject) return result;    
+      }  
+    return result
+  };
+
+  /**
+   * Iterates over an object's own enumerable properties, executing the `callback`
+   * for each property. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
+   * returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+   *   alert(key);
+   * });
+   * // => alerts '0', '1', and 'length' (order is not guaranteed)
+   */
+  var forOwn = function (collection, callback) {
+    var index, iterable = collection, result = iterable;
+    if (!iterable) return result;
+    if (!objectTypes[typeof iterable]) return result;
+    callback || (callback = identity);
+    
+      for (index in iterable) {
+        if (hasOwnProperty.call(iterable, index)) {    
+        if (callback(iterable[index], index, collection) === indicatorObject) return result;    
+        }
+      }  
+    return result
+  };
+
+  /**
+   * Checks if `value` is an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
+   * @example
+   *
+   * (function() { return _.isArray(arguments); })();
+   * // => false
+   *
+   * _.isArray([1, 2, 3]);
+   * // => true
+   */
+  var isArray = nativeIsArray || function(value) {
+    // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
+    // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
+    return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass;
+  };
+
+  /**
+   * Creates an array composed of the own enumerable property names of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   * @example
+   *
+   * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => ['one', 'two', 'three'] (order is not guaranteed)
+   */
+  var keys = !nativeKeys ? shimKeys : function(object) {
+    if (!isObject(object)) {
+      return [];
+    }
+    return nativeKeys(object);
+  };
+
+  /**
+   * A fallback implementation of `isPlainObject` that checks if a given `value`
+   * is an object created by the `Object` constructor, assuming objects created
+   * by the `Object` constructor have no inherited enumerable properties and that
+   * there are no `Object.prototype` extensions.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   */
+  function shimIsPlainObject(value) {
+    // avoid non-objects and false positives for `arguments` objects
+    var result = false;
+    if (!(value && typeof value == 'object') || isArguments(value)) {
+      return result;
+    }
+    // check that the constructor is `Object` (i.e. `Object instanceof Object`)
+    var ctor = value.constructor;
+    if ((!isFunction(ctor)) || ctor instanceof ctor) {
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return result === false || hasOwnProperty.call(value, result);
+    }
+    return result;
+  }
+
+  /**
+   * A fallback implementation of `Object.keys` that produces an array of the
+   * given object's own enumerable property names.
+   *
+   * @private
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   */
+  function shimKeys(object) {
+    var result = [];
+    forOwn(object, function(value, key) {
+      result.push(key);
+    });
+    return result;
+  }
+
+  /**
+   * Used to convert characters to HTML entities:
+   *
+   * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+   * don't require escaping in HTML and have no special meaning unless they're part
+   * of a tag or an unquoted attribute value.
+   * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+   */
+  var htmlEscapes = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#39;'
+  };
+
+  /** Used to convert HTML entities to characters */
+  var htmlUnescapes = invert(htmlEscapes);
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object. Subsequent sources will overwrite propery assignments of previous
+   * sources. If a `callback` function is passed, it will be executed to produce
+   * the assigned values. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @alias extend
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize assigning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * _.assign({ 'name': 'moe' }, { 'age': 40 });
+   * // => { 'name': 'moe', 'age': 40 }
+   *
+   * var defaults = _.partialRight(_.assign, function(a, b) {
+   *   return typeof a == 'undefined' ? b : a;
+   * });
+   *
+   * var food = { 'name': 'apple' };
+   * defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  function assign(object) {
+    if (!object) {
+      return object;
+    }
+    for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
+      var iterable = arguments[argsIndex];
+      if (iterable) {
+        for (var key in iterable) {
+          object[key] = iterable[key];
+        }
+      }
+    }
+    return object;
+  }
+
+  /**
+   * Creates a clone of `value`. If `deep` is `true`, nested objects will also
+   * be cloned, otherwise they will be assigned by reference. If a `callback`
+   * function is passed, it will be executed to produce the cloned values. If
+   * `callback` returns `undefined`, cloning will be handled by the method instead.
+   * The `callback` is bound to `thisArg` and invoked with one argument; (value).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to clone.
+   * @param {Boolean} [deep=false] A flag to indicate a deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
+   * @returns {Mixed} Returns the cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var shallow = _.clone(stooges);
+   * shallow[0] === stooges[0];
+   * // => true
+   *
+   * var deep = _.clone(stooges, true);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * _.mixin({
+   *   'clone': _.partialRight(_.clone, function(value) {
+   *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+   *   })
+   * });
+   *
+   * var clone = _.clone(document.body);
+   * clone.childNodes.length;
+   * // => 0
+   */
+  function clone(value) {
+    return isObject(value)
+      ? (isArray(value) ? slice(value) : assign({}, value))
+      : value
+  }
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object for all destination properties that resolve to `undefined`. Once a
+   * property is set, additional defaults of the same property will be ignored.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param- {Object} [guard] Internally used to allow working with `_.reduce`
+   *  without using its callback's `key` and `object` arguments as sources.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var food = { 'name': 'apple' };
+   * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  function defaults(object) {
+    if (!object) {
+      return object;
+    }
+    for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
+      var iterable = arguments[argsIndex];
+      if (iterable) {
+        for (var key in iterable) {
+          if (object[key] == null) {
+            object[key] = iterable[key];
+          }
+        }
+      }
+    }
+    return object;
+  }
+
+  /**
+   * Creates a sorted array of all enumerable properties, own and inherited,
+   * of `object` that have function values.
+   *
+   * @static
+   * @memberOf _
+   * @alias methods
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names that have function values.
+   * @example
+   *
+   * _.functions(_);
+   * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+   */
+  function functions(object) {
+    var result = [];
+    forIn(object, function(value, key) {
+      if (isFunction(value)) {
+        result.push(key);
+      }
+    });
+    return result.sort();
+  }
+
+  /**
+   * Checks if the specified object `property` exists and is a direct property,
+   * instead of an inherited property.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to check.
+   * @param {String} property The property to check for.
+   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+   * @example
+   *
+   * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+   * // => true
+   */
+  function has(object, property) {
+    return object ? hasOwnProperty.call(object, property) : false;
+  }
+
+  /**
+   * Creates an object composed of the inverted keys and values of the given `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to invert.
+   * @returns {Object} Returns the created inverted object.
+   * @example
+   *
+   *  _.invert({ 'first': 'moe', 'second': 'larry' });
+   * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
+   */
+  function invert(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      result[object[key]] = key;
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is a boolean value.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
+   * @example
+   *
+   * _.isBoolean(null);
+   * // => false
+   */
+  function isBoolean(value) {
+    return value === true || value === false || toString.call(value) == boolClass;
+  }
+
+  /**
+   * Checks if `value` is a date.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
+   * @example
+   *
+   * _.isDate(new Date);
+   * // => true
+   */
+  function isDate(value) {
+    return value instanceof Date || toString.call(value) == dateClass;
+  }
+
+  /**
+   * Checks if `value` is a DOM element.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
+   * @example
+   *
+   * _.isElement(document.body);
+   * // => true
+   */
+  function isElement(value) {
+    return value ? value.nodeType === 1 : false;
+  }
+
+  /**
+   * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+   * length of `0` and objects with no own enumerable properties are considered
+   * "empty".
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Array|Object|String} value The value to inspect.
+   * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
+   * @example
+   *
+   * _.isEmpty([1, 2, 3]);
+   * // => false
+   *
+   * _.isEmpty({});
+   * // => true
+   *
+   * _.isEmpty('');
+   * // => true
+   */
+  function isEmpty(value) {
+    if (!value) {
+      return true;
+    }
+    if (isArray(value) || isString(value)) {
+      return !value.length;
+    }
+    for (var key in value) {
+      if (hasOwnProperty.call(value, key)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Performs a deep comparison between two values to determine if they are
+   * equivalent to each other. If `callback` is passed, it will be executed to
+   * compare values. If `callback` returns `undefined`, comparisons will be handled
+   * by the method instead. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (a, b).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} a The value to compare.
+   * @param {Mixed} b The other value to compare.
+   * @param {Function} [callback] The function to customize comparing values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
+   * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
+   * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
+   * @example
+   *
+   * var moe = { 'name': 'moe', 'age': 40 };
+   * var copy = { 'name': 'moe', 'age': 40 };
+   *
+   * moe == copy;
+   * // => false
+   *
+   * _.isEqual(moe, copy);
+   * // => true
+   *
+   * var words = ['hello', 'goodbye'];
+   * var otherWords = ['hi', 'goodbye'];
+   *
+   * _.isEqual(words, otherWords, function(a, b) {
+   *   var reGreet = /^(?:hello|hi)$/i,
+   *       aGreet = _.isString(a) && reGreet.test(a),
+   *       bGreet = _.isString(b) && reGreet.test(b);
+   *
+   *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+   * });
+   * // => true
+   */
+  function isEqual(a, b, stackA, stackB) {
+    if (a === b) {
+      return a !== 0 || (1 / a == 1 / b);
+    }
+    var type = typeof a,
+        otherType = typeof b;
+
+    if (a === a &&
+        (!a || (type != 'function' && type != 'object')) &&
+        (!b || (otherType != 'function' && otherType != 'object'))) {
+      return false;
+    }
+    if (a == null || b == null) {
+      return a === b;
+    }
+    var className = toString.call(a),
+        otherClass = toString.call(b);
+
+    if (className != otherClass) {
+      return false;
+    }
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        return +a == +b;
+
+      case numberClass:
+        return a != +a
+          ? b != +b
+          : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+      case regexpClass:
+      case stringClass:
+        return a == b + '';
+    }
+    var isArr = className == arrayClass;
+    if (!isArr) {
+      if (a.__wrapped__ || b.__wrapped__) {
+        return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, stackA, stackB);
+      }
+      if (className != objectClass) {
+        return false;
+      }
+      var ctorA = a.constructor,
+          ctorB = b.constructor;
+
+      if (ctorA != ctorB && !(
+            isFunction(ctorA) && ctorA instanceof ctorA &&
+            isFunction(ctorB) && ctorB instanceof ctorB
+          )) {
+        return false;
+      }
+    }
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == a) {
+        return stackB[length] == b;
+      }
+    }
+    var result = true,
+        size = 0;
+
+    stackA.push(a);
+    stackB.push(b);
+
+    if (isArr) {
+      size = b.length;
+      result = size == a.length;
+
+      if (result) {
+        while (size--) {
+          if (!(result = isEqual(a[size], b[size], stackA, stackB))) {
+            break;
+          }
+        }
+      }
+      return result;
+    }
+    forIn(b, function(value, key, b) {
+      if (hasOwnProperty.call(b, key)) {
+        size++;
+        return !(result = hasOwnProperty.call(a, key) && isEqual(a[key], value, stackA, stackB)) && indicatorObject;
+      }
+    });
+
+    if (result) {
+      forIn(a, function(value, key, a) {
+        if (hasOwnProperty.call(a, key)) {
+          return !(result = --size > -1) && indicatorObject;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is, or can be coerced to, a finite number.
+   *
+   * Note: This is not the same as native `isFinite`, which will return true for
+   * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
+   * @example
+   *
+   * _.isFinite(-101);
+   * // => true
+   *
+   * _.isFinite('10');
+   * // => true
+   *
+   * _.isFinite(true);
+   * // => false
+   *
+   * _.isFinite('');
+   * // => false
+   *
+   * _.isFinite(Infinity);
+   * // => false
+   */
+  function isFinite(value) {
+    return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+  }
+
+  /**
+   * Checks if `value` is a function.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
+   * @example
+   *
+   * _.isFunction(_);
+   * // => true
+   */
+  function isFunction(value) {
+    return typeof value == 'function';
+  }
+  // fallback for older versions of Chrome and Safari
+  if (isFunction(/x/)) {
+    isFunction = function(value) {
+      return value instanceof Function || toString.call(value) == funcClass;
+    };
+  }
+
+  /**
+   * Checks if `value` is the language type of Object.
+   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
+   * @example
+   *
+   * _.isObject({});
+   * // => true
+   *
+   * _.isObject([1, 2, 3]);
+   * // => true
+   *
+   * _.isObject(1);
+   * // => false
+   */
+  function isObject(value) {
+    // check if the value is the ECMAScript language type of Object
+    // http://es5.github.com/#x8
+    // and avoid a V8 bug
+    // http://code.google.com/p/v8/issues/detail?id=2291
+    return value ? objectTypes[typeof value] : false;
+  }
+
+  /**
+   * Checks if `value` is `NaN`.
+   *
+   * Note: This is not the same as native `isNaN`, which will return `true` for
+   * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
+   * @example
+   *
+   * _.isNaN(NaN);
+   * // => true
+   *
+   * _.isNaN(new Number(NaN));
+   * // => true
+   *
+   * isNaN(undefined);
+   * // => true
+   *
+   * _.isNaN(undefined);
+   * // => false
+   */
+  function isNaN(value) {
+    // `NaN` as a primitive is the only value that is not equal to itself
+    // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+    return isNumber(value) && value != +value
+  }
+
+  /**
+   * Checks if `value` is `null`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
+   * @example
+   *
+   * _.isNull(null);
+   * // => true
+   *
+   * _.isNull(undefined);
+   * // => false
+   */
+  function isNull(value) {
+    return value === null;
+  }
+
+  /**
+   * Checks if `value` is a number.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
+   * @example
+   *
+   * _.isNumber(8.4 * 5);
+   * // => true
+   */
+  function isNumber(value) {
+    return typeof value == 'number' || toString.call(value) == numberClass;
+  }
+
+  /**
+   * Checks if `value` is a regular expression.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
+   * @example
+   *
+   * _.isRegExp(/moe/);
+   * // => true
+   */
+  function isRegExp(value) {
+    return value instanceof RegExp || toString.call(value) == regexpClass;
+  }
+
+  /**
+   * Checks if `value` is a string.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
+   * @example
+   *
+   * _.isString('moe');
+   * // => true
+   */
+  function isString(value) {
+    return typeof value == 'string' || toString.call(value) == stringClass;
+  }
+
+  /**
+   * Checks if `value` is `undefined`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
+   * @example
+   *
+   * _.isUndefined(void 0);
+   * // => true
+   */
+  function isUndefined(value) {
+    return typeof value == 'undefined';
+  }
+
+  /**
+   * Creates a shallow clone of `object` excluding the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a `callback` function is passed, it will be executed
+   * for each property in the `object`, omitting the properties `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
+   *  or the function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object without the omitted properties.
+   * @example
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, 'age');
+   * // => { 'name': 'moe' }
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
+   *   return typeof value == 'number';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function omit(object) {
+    var props = concat.apply(arrayRef, arguments),
+        result = {};
+
+    forIn(object, function(value, key) {
+      if (indexOf(props, key, 1) < 0) {
+        result[key] = value;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Creates a two dimensional array of the given object's key-value pairs,
+   * i.e. `[[key1, value1], [key2, value2]]`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns new array of key-value pairs.
+   * @example
+   *
+   * _.pairs({ 'moe': 30, 'larry': 40 });
+   * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
+   */
+  function pairs(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      var key = props[index];
+      result[index] = [key, object[key]];
+    }
+    return result;
+  }
+
+  /**
+   * Creates a shallow clone of `object` composed of the specified properties.
+   * Property names may be specified as individual arguments or as arrays of property
+   * names. If `callback` is passed, it will be executed for each property in the
+   * `object`, picking the properties `callback` returns truthy for. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
+   *  per iteration or properties to pick, either as individual arguments or arrays.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object composed of the picked properties.
+   * @example
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
+   * // => { 'name': 'moe' }
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
+   *   return key.charAt(0) != '_';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function pick(object) {
+    var index = 0,
+        props = concat.apply(arrayRef, arguments),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var prop = props[index];
+      if (prop in object) {
+        result[prop] = object[prop];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array composed of the own enumerable property values of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => [1, 2, 3]
+   */
+  function values(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = object[props[index]];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if a given `target` element is present in a `collection` using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @alias include
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Mixed} target The value to check for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
+   * @example
+   *
+   * _.contains([1, 2, 3], 1);
+   * // => true
+   *
+   * _.contains([1, 2, 3], 1, 2);
+   * // => false
+   *
+   * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+   * // => true
+   *
+   * _.contains('curly', 'ur');
+   * // => true
+   */
+  function contains(collection, target) {
+    var length = collection ? collection.length : 0,
+        result = false;
+    if (typeof length == 'number') {
+      result = indexOf(collection, target) > -1;
+    } else {
+      each(collection, function(value) {
+        return (result = value === target) && indicatorObject;
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the given `callback`. The corresponding value of each key
+   * is the number of times the key was returned by the `callback`. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy(['one', 'two', 'three'], 'length');
+   * // => { '3': 2, '5': 1 }
+   */
+  function countBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+    return result;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **all** elements of a
+   * `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias all
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if all elements pass the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.every([true, 1, null, 'yes'], Boolean);
+   * // => false
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.every(stooges, 'age');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.every(stooges, { 'age': 50 });
+   * // => false
+   */
+  function every(collection, callback, thisArg) {
+    var result = true;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (!(result = !!callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return !(result = !!callback(value, index, collection)) && indicatorObject;
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias select
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that passed the callback check.
+   * @example
+   *
+   * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [2, 4, 6]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.filter(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.filter(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   */
+  function filter(collection, callback, thisArg) {
+    var result = [];
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning the first that the `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias detect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the element that passed the callback check,
+   *  else `undefined`.
+   * @example
+   *
+   * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => 2
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },
+   *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * var veggie = _.find(food, { 'type': 'vegetable' });
+   * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
+   *
+   * // using "_.pluck" callback shorthand
+   * var healthy = _.find(food, 'organic');
+   * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
+   */
+  function find(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, index, collection) {
+      if (callback(value, index, collection)) {
+        result = value;
+        return indicatorObject;
+      }
+    });
+    return result;
+  }
+
+  function findWhere(object, properties) {
+    return where(object, properties, true);
+  }
+
+  /**
+   * Iterates over a `collection`, executing the `callback` for each element in
+   * the `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection). Callbacks may exit iteration early
+   * by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias each
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   * @example
+   *
+   * _([1, 2, 3]).forEach(alert).join(',');
+   * // => alerts each number and returns '1,2,3'
+   *
+   * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
+   * // => alerts each number value (order is not guaranteed)
+   */
+  function forEach(collection, callback, thisArg) {
+    if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (callback(collection[index], index, collection) === indicatorObject) {
+          break;
+        }
+      }
+    } else {
+      each(collection, callback, thisArg);
+    };
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the `callback`. The corresponding value of each key is
+   * an array of elements passed to `callback` that returned the key. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * // using "_.pluck" callback shorthand
+   * _.groupBy(['one', 'two', 'three'], 'length');
+   * // => { '3': ['one', 'two'], '5': ['three'] }
+   */
+  function groupBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+    return result;
+  }
+
+  /**
+   * Invokes the method named by `methodName` on each element in the `collection`,
+   * returning an array of the results of each invoked method. Additional arguments
+   * will be passed to each invoked method. If `methodName` is a function, it will
+   * be invoked for, and `this` bound to, each element in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|String} methodName The name of the method to invoke or
+   *  the function invoked per iteration.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+   * @returns {Array} Returns a new array of the results of each invoked method.
+   * @example
+   *
+   * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+   * // => [[1, 5, 7], [1, 2, 3]]
+   *
+   * _.invoke([123, 456], String.prototype.split, '');
+   * // => [['1', '2', '3'], ['4', '5', '6']]
+   */
+  function invoke(collection, methodName) {
+    var args = slice(arguments, 2),
+        index = -1,
+        isFunc = typeof methodName == 'function',
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+    });
+    return result;
+  }
+
+  /**
+   * Creates an array of values by running each element in the `collection`
+   * through the `callback`. The `callback` is bound to `thisArg` and invoked with
+   * three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias collect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * _.map([1, 2, 3], function(num) { return num * 3; });
+   * // => [3, 6, 9]
+   *
+   * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+   * // => [3, 6, 9] (order is not guaranteed)
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.map(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  function map(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    if (isArray(collection)) {
+      while (++index < length) {
+        result[index] = callback(collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, key, collection) {
+        result[++index] = callback(value, key, collection);
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the maximum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the maximum value.
+   * @example
+   *
+   * _.max([4, 2, 8, 6]);
+   * // => 8
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.max(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'larry', 'age': 50 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.max(stooges, 'age');
+   * // => { 'name': 'larry', 'age': 50 };
+   */
+  function max(collection, callback, thisArg) {
+    var computed = -Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value > result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current > computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the minimum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the minimum value.
+   * @example
+   *
+   * _.min([4, 2, 8, 6]);
+   * // => 2
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.min(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'moe', 'age': 40 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.min(stooges, 'age');
+   * // => { 'name': 'moe', 'age': 40 };
+   */
+  function min(collection, callback, thisArg) {
+    var computed = Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value < result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current < computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the value of a specified property from all elements in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {String} property The property to pluck.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.pluck(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  var pluck = map;
+
+  /**
+   * Reduces a `collection` to a value that is the accumulated result of running
+   * each element in the `collection` through the `callback`, where each successive
+   * `callback` execution consumes the return value of the previous execution.
+   * If `accumulator` is not passed, the first element of the `collection` will be
+   * used as the initial `accumulator` value. The `callback` is bound to `thisArg`
+   * and invoked with four arguments; (accumulator, value, index|key, collection).
+   *
+   * @static
+   * @memberOf _
+   * @alias foldl, inject
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var sum = _.reduce([1, 2, 3], function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+   *   result[key] = num * 3;
+   *   return result;
+   * }, {});
+   * // => { 'a': 3, 'b': 6, 'c': 9 }
+   */
+  function reduce(collection, callback, accumulator, thisArg) {
+    var noaccum = arguments.length < 3;
+    callback = createCallback(callback, thisArg, 4);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      if (noaccum) {
+        accumulator = collection[++index];
+      }
+      while (++index < length) {
+        accumulator = callback(accumulator, collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection)
+      });
+    }
+    return accumulator;
+  }
+
+  /**
+   * This method is similar to `_.reduce`, except that it iterates over a
+   * `collection` from right to left.
+   *
+   * @static
+   * @memberOf _
+   * @alias foldr
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var list = [[0, 1], [2, 3], [4, 5]];
+   * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+   * // => [4, 5, 2, 3, 0, 1]
+   */
+  function reduceRight(collection, callback, accumulator, thisArg) {
+    var iterable = collection,
+        length = collection ? collection.length : 0,
+        noaccum = arguments.length < 3;
+
+    if (typeof length != 'number') {
+      var props = keys(collection);
+      length = props.length;
+    }
+    callback = createCallback(callback, thisArg, 4);
+    forEach(collection, function(value, index, collection) {
+      index = props ? props[--length] : --length;
+      accumulator = noaccum
+        ? (noaccum = false, iterable[index])
+        : callback(accumulator, iterable[index], index, collection);
+    });
+    return accumulator;
+  }
+
+  /**
+   * The opposite of `_.filter`, this method returns the elements of a
+   * `collection` that `callback` does **not** return truthy for.
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that did **not** pass the
+   *  callback check.
+   * @example
+   *
+   * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [1, 3, 5]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.reject(food, 'organic');
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.reject(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   */
+  function reject(collection, callback, thisArg) {
+    callback = createCallback(callback, thisArg);
+    return filter(collection, function(value, index, collection) {
+      return !callback(value, index, collection);
+    });
+  }
+
+  /**
+   * Creates an array of shuffled `array` values, using a version of the
+   * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to shuffle.
+   * @returns {Array} Returns a new shuffled collection.
+   * @example
+   *
+   * _.shuffle([1, 2, 3, 4, 5, 6]);
+   * // => [4, 1, 6, 3, 5, 2]
+   */
+  function shuffle(collection) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      var rand = floor(nativeRandom() * (++index + 1));
+      result[index] = result[rand];
+      result[rand] = value;
+    });
+    return result;
+  }
+
+  /**
+   * Gets the size of the `collection` by returning `collection.length` for arrays
+   * and array-like objects or the number of own enumerable properties for objects.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to inspect.
+   * @returns {Number} Returns `collection.length` or number of own enumerable properties.
+   * @example
+   *
+   * _.size([1, 2]);
+   * // => 2
+   *
+   * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => 3
+   *
+   * _.size('curly');
+   * // => 5
+   */
+  function size(collection) {
+    var length = collection ? collection.length : 0;
+    return typeof length == 'number' ? length : keys(collection).length;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **any** element of a
+   * `collection`. The function returns as soon as it finds passing value, and
+   * does not iterate over the entire `collection`. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias any
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if any element passes the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.some([null, 0, 'yes', false], Boolean);
+   * // => true
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.some(food, 'organic');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.some(food, { 'type': 'meat' });
+   * // => false
+   */
+  function some(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if ((result = callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return (result = callback(value, index, collection)) && indicatorObject;
+      });
+    }
+    return !!result;
+  }
+
+  /**
+   * Creates an array of elements, sorted in ascending order by the results of
+   * running each element in the `collection` through the `callback`. This method
+   * performs a stable sort, that is, it will preserve the original sort order of
+   * equal elements. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of sorted elements.
+   * @example
+   *
+   * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+   * // => [3, 1, 2]
+   *
+   * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+   * // => [3, 1, 2]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
+   * // => ['apple', 'banana', 'strawberry']
+   */
+  function sortBy(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    forEach(collection, function(value, key, collection) {
+      result[++index] = {
+        'criteria': callback(value, key, collection),
+        'index': index,
+        'value': value
+      };
+    });
+
+    length = result.length;
+    result.sort(compareAscending);
+    while (length--) {
+      result[length] = result[length].value;
+    }
+    return result;
+  }
+
+  /**
+   * Converts the `collection` to an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to convert.
+   * @returns {Array} Returns the new converted array.
+   * @example
+   *
+   * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+   * // => [2, 3, 4]
+   */
+  function toArray(collection) {
+    if (collection && typeof collection.length == 'number') {
+      return  slice(collection);
+    }
+    return values(collection);
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * that have the given `properties`. When checking `properties`, this method
+   * performs a deep comparison between values to determine if they are equivalent
+   * to each other.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Object} properties The object of property values to filter by.
+   * @returns {Array} Returns a new array of elements that have the given `properties`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.where(stooges, { 'age': 40 });
+   * // => [{ 'name': 'moe', 'age': 40 }]
+   */
+  function where(collection, properties, first) {
+    return (first && isEmpty(properties))
+      ? null
+      : (first ? find : filter)(collection, properties);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array with all falsey values of `array` removed. The values
+   * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.compact([0, 1, false, 2, '', 3]);
+   * // => [1, 2, 3]
+   */
+  function compact(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (value) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of `array` elements not present in the other arrays
+   * using strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Array} [array1, array2, ...] Arrays to check.
+   * @returns {Array} Returns a new array of `array` elements not present in the
+   *  other arrays.
+   * @example
+   *
+   * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+   * // => [1, 3, 4]
+   */
+  function difference(array) {
+    var index = -1,
+        length = array.length,
+        flattened = concat.apply(arrayRef, arguments),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index]
+      if (indexOf(flattened, value, length) < 0) {
+        result.push(value);
+      }
+    }
+    return result
+  }
+
+  /**
+   * Gets the first element of the `array`. If a number `n` is passed, the first
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the first elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias head, take
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the first element(s) of `array`.
+   * @example
+   *
+   * _.first([1, 2, 3]);
+   * // => 1
+   *
+   * _.first([1, 2, 3], 2);
+   * // => [1, 2]
+   *
+   * _.first([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [1, 2]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.first(food, 'organic');
+   * // => [{ 'name': 'banana', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.first(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
+   */
+  function first(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = createCallback(callback, thisArg);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[0];
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+  }
+
+  /**
+   * Flattens a nested array (the nesting can be to any depth). If `shallow` is
+   * truthy, `array` will only be flattened a single level.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @param {Boolean} shallow A flag to indicate only flattening a single level.
+   * @returns {Array} Returns a new flattened array.
+   * @example
+   *
+   * _.flatten([1, [2], [3, [[4]]]]);
+   * // => [1, 2, 3, 4];
+   *
+   * _.flatten([1, [2], [3, [[4]]]], true);
+   * // => [1, 2, 3, [[4]]];
+   */
+  function flatten(array, shallow) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+
+      // recursively flatten arrays (susceptible to call stack limits)
+      if (isArray(value)) {
+        push.apply(result, shallow ? value : flatten(value));
+      } else {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the index at which the first occurrence of `value` is found using
+   * strict equality for comparisons, i.e. `===`. If the `array` is already
+   * sorted, passing `true` for `fromIndex` will run a faster binary search.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
+   *  perform a binary search on a sorted `array`.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 1
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 4
+   *
+   * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+   * // => 2
+   */
+  function indexOf(array, value, fromIndex) {
+    var index = -1,
+        length = array ? array.length : 0;
+
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
+    } else if (fromIndex) {
+      index = sortedIndex(array, value);
+      return array[index] === value ? index : -1;
+    }
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Gets all but the last element of `array`. If a number `n` is passed, the
+   * last `n` elements are excluded from the result. If a `callback` function
+   * is passed, the last elements the `callback` returns truthy for are excluded
+   * from the result. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.initial([1, 2, 3]);
+   * // => [1, 2]
+   *
+   * _.initial([1, 2, 3], 2);
+   * // => [1]
+   *
+   * _.initial([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [1]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.initial(food, 'organic');
+   * // => [{ 'name': 'beet',   'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.initial(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'banana', 'type': 'fruit' }]
+   */
+  function initial(array, callback, thisArg) {
+    if (!array) {
+      return [];
+    }
+    var n = 0,
+        length = array.length;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = length;
+      callback = createCallback(callback, thisArg);
+      while (index-- && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : callback || n;
+    }
+    return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+  }
+
+  /**
+   * Computes the intersection of all the passed-in arrays using strict equality
+   * for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique elements that are present
+   *  in **all** of the arrays.
+   * @example
+   *
+   * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2]
+   */
+  function intersection(array) {
+    var args = arguments,
+        argsLength = args.length,
+        index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    outer:
+    while (++index < length) {
+      var value = array[index];
+      if (indexOf(result, value) < 0) {
+        var argsIndex = argsLength;
+        while (--argsIndex) {
+          if (indexOf(args[argsIndex], value) < 0) {
+            continue outer;
+          }
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the last element of the `array`. If a number `n` is passed, the last
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the last elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the last element(s) of `array`.
+   * @example
+   *
+   * _.last([1, 2, 3]);
+   * // => 3
+   *
+   * _.last([1, 2, 3], 2);
+   * // => [2, 3]
+   *
+   * _.last([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [2, 3]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.last(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.last(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
+   */
+  function last(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = createCallback(callback, thisArg);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[length - 1];
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+  }
+
+  /**
+   * Gets the index at which the last occurrence of `value` is found using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=array.length-1] The index to search from.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 4
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 1
+   */
+  function lastIndexOf(array, value, fromIndex) {
+    var index = array ? array.length : 0;
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+    }
+    while (index--) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Creates an object composed from arrays of `keys` and `values`. Pass either
+   * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
+   * two arrays, one of `keys` and one of corresponding `values`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} keys The array of keys.
+   * @param {Array} [values=[]] The array of values.
+   * @returns {Object} Returns an object composed of the given keys and
+   *  corresponding values.
+   * @example
+   *
+   * _.object(['moe', 'larry'], [30, 40]);
+   * // => { 'moe': 30, 'larry': 40 }
+   */
+  function object(keys, values) {
+    var index = -1,
+        length = keys ? keys.length : 0,
+        result = {};
+
+    while (++index < length) {
+      var key = keys[index];
+      if (values) {
+        result[key] = values[index];
+      } else {
+        result[key[0]] = key[1];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of numbers (positive and/or negative) progressing from
+   * `start` up to but not including `end`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Number} [start=0] The start of the range.
+   * @param {Number} end The end of the range.
+   * @param {Number} [step=1] The value to increment or descrement by.
+   * @returns {Array} Returns a new range array.
+   * @example
+   *
+   * _.range(10);
+   * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+   *
+   * _.range(1, 11);
+   * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+   *
+   * _.range(0, 30, 5);
+   * // => [0, 5, 10, 15, 20, 25]
+   *
+   * _.range(0, -10, -1);
+   * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+   *
+   * _.range(0);
+   * // => []
+   */
+  function range(start, end, step) {
+    start = +start || 0;
+    step = +step || 1;
+
+    if (end == null) {
+      end = start;
+      start = 0;
+    }
+    // use `Array(length)` so V8 will avoid the slower "dictionary" mode
+    // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+    var index = -1,
+        length = nativeMax(0, ceil((end - start) / step)),
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = start;
+      start += step;
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.initial`, this method gets all but the first value of `array`.
+   * If a number `n` is passed, the first `n` values are excluded from the result.
+   * If a `callback` function is passed, the first elements the `callback` returns
+   * truthy for are excluded from the result. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias drop, tail
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.rest([1, 2, 3]);
+   * // => [2, 3]
+   *
+   * _.rest([1, 2, 3], 2);
+   * // => [3]
+   *
+   * _.rest([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [3]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.rest(food, 'organic');
+   * // => [{ 'name': 'beet', 'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.rest(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }]
+   */
+  function rest(array, callback, thisArg) {
+    if (typeof callback != 'number' && callback != null) {
+      var n = 0,
+          index = -1,
+          length = array ? array.length : 0;
+
+      callback = createCallback(callback, thisArg);
+      while (++index < length && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+    }
+    return slice(array, n);
+  }
+
+  /**
+   * Uses a binary search to determine the smallest index at which the `value`
+   * should be inserted into `array` in order to maintain the sort order of the
+   * sorted `array`. If `callback` is passed, it will be executed for `value` and
+   * each element in `array` to compute their sort ranking. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to iterate over.
+   * @param {Mixed} value The value to evaluate.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Number} Returns the index at which the value should be inserted
+   *  into `array`.
+   * @example
+   *
+   * _.sortedIndex([20, 30, 50], 40);
+   * // => 2
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+   * // => 2
+   *
+   * var dict = {
+   *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+   * };
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return dict.wordToNumber[word];
+   * });
+   * // => 2
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return this.wordToNumber[word];
+   * }, dict);
+   * // => 2
+   */
+  function sortedIndex(array, value, callback, thisArg) {
+    var low = 0,
+        high = array ? array.length : low;
+
+    // explicitly reference `identity` for better inlining in Firefox
+    callback = callback ? createCallback(callback, thisArg, 1) : identity;
+    value = callback(value);
+
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      callback(array[mid]) < value
+        ? low = mid + 1
+        : high = mid;
+    }
+    return low;
+  }
+
+  /**
+   * Computes the union of the passed-in arrays using strict equality for
+   * comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique values, in order, that are
+   *  present in one or more of the arrays.
+   * @example
+   *
+   * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2, 3, 101, 10]
+   */
+  function union() {
+    return uniq(concat.apply(arrayRef, arguments));
+  }
+
+  /**
+   * Creates a duplicate-value-free version of the `array` using strict equality
+   * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
+   * for `isSorted` will run a faster algorithm. If `callback` is passed, each
+   * element of `array` is passed through a callback` before uniqueness is computed.
+   * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias unique
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a duplicate-value-free array.
+   * @example
+   *
+   * _.uniq([1, 2, 1, 3, 1]);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 1, 2, 2, 3], true);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
+   * // => [1, 2, 3]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+   * // => [{ 'x': 1 }, { 'x': 2 }]
+   */
+  function uniq(array, isSorted, callback, thisArg) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [],
+        seen = result;
+
+    if (typeof isSorted == 'function') {
+      thisArg = callback;
+      callback = isSorted;
+      isSorted = false;
+    }
+    if (callback) {
+      seen = [];
+      callback = createCallback(callback, thisArg);
+    }
+    while (++index < length) {
+      var value = array[index],
+          computed = callback ? callback(value, index, array) : value;
+
+      if (isSorted
+            ? !index || seen[seen.length - 1] !== computed
+            : indexOf(seen, computed) < 0
+          ) {
+        if (callback) {
+          seen.push(computed);
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array with all occurrences of the passed values removed using
+   * strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to filter.
+   * @param {Mixed} [value1, value2, ...] Values to remove.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+   * // => [2, 3, 4]
+   */
+  function without(array) {
+    var index = -1,
+        length = array.length,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index]
+      if (indexOf(arguments, value, 1) < 0) {
+        result.push(value);
+      }
+    }
+    return result
+  }
+
+  /**
+   * Groups the elements of each array at their corresponding indexes. Useful for
+   * separate data sources that are coordinated through matching array indexes.
+   * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
+   * in a similar fashion.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of grouped elements.
+   * @example
+   *
+   * _.zip(['moe', 'larry'], [30, 40], [true, false]);
+   * // => [['moe', 30, true], ['larry', 40, false]]
+   */
+  function zip(array) {
+    var index = -1,
+        length = array ? max(pluck(arguments, 'length')) : 0,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = pluck(arguments, index);
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function that is restricted to executing `func` only after it is
+   * called `n` times. The `func` is executed with the `this` binding of the
+   * created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Number} n The number of times the function must be called before
+   * it is executed.
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var renderNotes = _.after(notes.length, render);
+   * _.forEach(notes, function(note) {
+   *   note.asyncSave({ 'success': renderNotes });
+   * });
+   * // `renderNotes` is run once, after all notes have saved
+   */
+  function after(n, func) {
+    if (n < 1) {
+      return func();
+    }
+    return function() {
+      if (--n < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this`
+   * binding of `thisArg` and prepends any additional `bind` arguments to those
+   * passed to the bound function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to bind.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var func = function(greeting) {
+   *   return greeting + ' ' + this.name;
+   * };
+   *
+   * func = _.bind(func, { 'name': 'moe' }, 'hi');
+   * func();
+   * // => 'hi moe'
+   */
+  function bind(func, thisArg) {
+    // use `Function#bind` if it exists and is fast
+    // (in V8 `Function#bind` is slower except when partially applied)
+    return isBindFast || (nativeBind && arguments.length > 2)
+      ? nativeBind.call.apply(nativeBind, arguments)
+      : createBound(func, thisArg, slice(arguments, 2));
+  }
+
+  /**
+   * Binds methods on `object` to `object`, overwriting the existing method.
+   * Method names may be specified as individual arguments or as arrays of method
+   * names. If no method names are provided, all the function properties of `object`
+   * will be bound.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object to bind and assign the bound methods to.
+   * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * var view = {
+   *  'label': 'docs',
+   *  'onClick': function() { alert('clicked ' + this.label); }
+   * };
+   *
+   * _.bindAll(view);
+   * jQuery('#docs').on('click', view.onClick);
+   * // => alerts 'clicked docs', when the button is clicked
+   */
+  function bindAll(object) {
+    var funcs = concat.apply(arrayRef, arguments),
+        index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
+        length = funcs.length;
+
+    while (++index < length) {
+      var key = funcs[index];
+      object[key] = bind(object[key], object);
+    }
+    return object;
+  }
+
+  /**
+   * Creates a function that is the composition of the passed functions,
+   * where each function consumes the return value of the function that follows.
+   * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+   * Each function is executed with the `this` binding of the composed function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} [func1, func2, ...] Functions to compose.
+   * @returns {Function} Returns the new composed function.
+   * @example
+   *
+   * var greet = function(name) { return 'hi ' + name; };
+   * var exclaim = function(statement) { return statement + '!'; };
+   * var welcome = _.compose(exclaim, greet);
+   * welcome('moe');
+   * // => 'hi moe!'
+   */
+  function compose() {
+    var funcs = arguments;
+    return function() {
+      var args = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        args = [funcs[length].apply(this, args)];
+      }
+      return args[0];
+    };
+  }
+
+  /**
+   * Creates a function that will delay the execution of `func` until after
+   * `wait` milliseconds have elapsed since the last time it was invoked. Pass
+   * `true` for `immediate` to cause debounce to invoke `func` on the leading,
+   * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
+   * the debounced function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to debounce.
+   * @param {Number} wait The number of milliseconds to delay.
+   * @param {Boolean} immediate A flag to indicate execution is on the leading
+   *  edge of the timeout.
+   * @returns {Function} Returns the new debounced function.
+   * @example
+   *
+   * var lazyLayout = _.debounce(calculateLayout, 300);
+   * jQuery(window).on('resize', lazyLayout);
+   */
+  function debounce(func, wait, immediate) {
+    var args,
+        result,
+        thisArg,
+        timeoutId;
+
+    function delayed() {
+      timeoutId = null;
+      if (!immediate) {
+        result = func.apply(thisArg, args);
+      }
+    }
+    return function() {
+      var isImmediate = immediate && !timeoutId;
+      args = arguments;
+      thisArg = this;
+
+      clearTimeout(timeoutId);
+      timeoutId = setTimeout(delayed, wait);
+
+      if (isImmediate) {
+        result = func.apply(thisArg, args);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Executes the `func` function after `wait` milliseconds. Additional arguments
+   * will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to delay.
+   * @param {Number} wait The number of milliseconds to delay execution.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * var log = _.bind(console.log, console);
+   * _.delay(log, 1000, 'logged later');
+   * // => 'logged later' (Appears after one second.)
+   */
+  function delay(func, wait) {
+    var args = slice(arguments, 2);
+    return setTimeout(function() { func.apply(undefined, args); }, wait);
+  }
+
+  /**
+   * Defers executing the `func` function until the current call stack has cleared.
+   * Additional arguments will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to defer.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * _.defer(function() { alert('deferred'); });
+   * // returns from the function before `alert` is called
+   */
+  function defer(func) {
+    var args = slice(arguments, 1);
+    return setTimeout(function() { func.apply(undefined, args); }, 1);
+  }
+  // use `setImmediate` if it's available in Node.js
+  if (isV8 && freeModule && typeof setImmediate == 'function') {
+    defer = bind(setImmediate, window);
+  }
+
+  /**
+   * Creates a function that memoizes the result of `func`. If `resolver` is
+   * passed, it will be used to determine the cache key for storing the result
+   * based on the arguments passed to the memoized function. By default, the first
+   * argument passed to the memoized function is used as the cache key. The `func`
+   * is executed with the `this` binding of the memoized function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to have its output memoized.
+   * @param {Function} [resolver] A function used to resolve the cache key.
+   * @returns {Function} Returns the new memoizing function.
+   * @example
+   *
+   * var fibonacci = _.memoize(function(n) {
+   *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+   * });
+   */
+  function memoize(func, resolver) {
+    var cache = {};
+    return function() {
+      var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
+      return hasOwnProperty.call(cache, key)
+        ? cache[key]
+        : (cache[key] = func.apply(this, arguments));
+    };
+  }
+
+  /**
+   * Creates a function that is restricted to execute `func` once. Repeat calls to
+   * the function will return the value of the first call. The `func` is executed
+   * with the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var initialize = _.once(createApplication);
+   * initialize();
+   * initialize();
+   * // `initialize` executes `createApplication` once
+   */
+  function once(func) {
+    var ran,
+        result;
+
+    return function() {
+      if (ran) {
+        return result;
+      }
+      ran = true;
+      result = func.apply(this, arguments);
+
+      // clear the `func` variable so the function may be garbage collected
+      func = null;
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with any additional
+   * `partial` arguments prepended to those passed to the new function. This
+   * method is similar to `_.bind`, except it does **not** alter the `this` binding.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var greet = function(greeting, name) { return greeting + ' ' + name; };
+   * var hi = _.partial(greet, 'hi');
+   * hi('moe');
+   * // => 'hi moe'
+   */
+  function partial(func) {
+    return createBound(func, slice(arguments, 1));
+  }
+
+  /**
+   * Creates a function that, when executed, will only call the `func`
+   * function at most once per every `wait` milliseconds. If the throttled
+   * function is invoked more than once during the `wait` timeout, `func` will
+   * also be called on the trailing edge of the timeout. Subsequent calls to the
+   * throttled function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to throttle.
+   * @param {Number} wait The number of milliseconds to throttle executions to.
+   * @returns {Function} Returns the new throttled function.
+   * @example
+   *
+   * var throttled = _.throttle(updatePosition, 100);
+   * jQuery(window).on('scroll', throttled);
+   */
+  function throttle(func, wait) {
+    var args,
+        result,
+        thisArg,
+        timeoutId,
+        lastCalled = 0;
+
+    function trailingCall() {
+      lastCalled = new Date;
+      timeoutId = null;
+      result = func.apply(thisArg, args);
+    }
+    return function() {
+      var now = new Date,
+          remaining = wait - (now - lastCalled);
+
+      args = arguments;
+      thisArg = this;
+
+      if (remaining <= 0) {
+        clearTimeout(timeoutId);
+        timeoutId = null;
+        lastCalled = now;
+        result = func.apply(thisArg, args);
+      }
+      else if (!timeoutId) {
+        timeoutId = setTimeout(trailingCall, remaining);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that passes `value` to the `wrapper` function as its
+   * first argument. Additional arguments passed to the function are appended
+   * to those passed to the `wrapper` function. The `wrapper` is executed with
+   * the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Mixed} value The value to wrap.
+   * @param {Function} wrapper The wrapper function.
+   * @returns {Function} Returns the new function.
+   * @example
+   *
+   * var hello = function(name) { return 'hello ' + name; };
+   * hello = _.wrap(hello, function(func) {
+   *   return 'before, ' + func('moe') + ', after';
+   * });
+   * hello();
+   * // => 'before, hello moe, after'
+   */
+  function wrap(value, wrapper) {
+    return function() {
+      var args = [value];
+      push.apply(args, arguments);
+      return wrapper.apply(this, args);
+    };
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+   * corresponding HTML entities.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to escape.
+   * @returns {String} Returns the escaped string.
+   * @example
+   *
+   * _.escape('Moe, Larry & Curly');
+   * // => 'Moe, Larry &amp; Curly'
+   */
+  function escape(string) {
+    return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
+  }
+
+  /**
+   * This function returns the first argument passed to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Mixed} value Any value.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * var moe = { 'name': 'moe' };
+   * moe === _.identity(moe);
+   * // => true
+   */
+  function identity(value) {
+    return value;
+  }
+
+  /**
+   * Adds functions properties of `object` to the `lodash` function and chainable
+   * wrapper.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object of function properties to add to `lodash`.
+   * @example
+   *
+   * _.mixin({
+   *   'capitalize': function(string) {
+   *     return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+   *   }
+   * });
+   *
+   * _.capitalize('moe');
+   * // => 'Moe'
+   *
+   * _('moe').capitalize();
+   * // => 'Moe'
+   */
+  function mixin(object) {
+    forEach(functions(object), function(methodName) {
+      var func = lodash[methodName] = object[methodName];
+
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        
+        var result = func.apply(lodash, args);
+        if (this.__chain__) {
+          result = new lodash(result);
+          result.__chain__ = true;
+        }
+        return result;
+      };
+    });
+  }
+
+  /**
+   * Reverts the '_' variable to its previous value and returns a reference to
+   * the `lodash` function.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @returns {Function} Returns the `lodash` function.
+   * @example
+   *
+   * var lodash = _.noConflict();
+   */
+  function noConflict() {
+    window._ = oldDash;
+    return this;
+  }
+
+  /**
+   * Produces a random number between `min` and `max` (inclusive). If only one
+   * argument is passed, a number between `0` and the given number will be returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} [min=0] The minimum possible value.
+   * @param {Number} [max=1] The maximum possible value.
+   * @returns {Number} Returns a random number.
+   * @example
+   *
+   * _.random(0, 5);
+   * // => a number between 0 and 5
+   *
+   * _.random(5);
+   * // => also a number between 0 and 5
+   */
+  function random(min, max) {
+    if (min == null && max == null) {
+      max = 1;
+    }
+    min = +min || 0;
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + floor(nativeRandom() * ((+max || 0) - min + 1));
+  }
+
+  /**
+   * Resolves the value of `property` on `object`. If `property` is a function,
+   * it will be invoked and its result returned, else the property value is
+   * returned. If `object` is falsey, then `null` is returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object to inspect.
+   * @param {String} property The property to get the value of.
+   * @returns {Mixed} Returns the resolved value.
+   * @example
+   *
+   * var object = {
+   *   'cheese': 'crumpets',
+   *   'stuff': function() {
+   *     return 'nonsense';
+   *   }
+   * };
+   *
+   * _.result(object, 'cheese');
+   * // => 'crumpets'
+   *
+   * _.result(object, 'stuff');
+   * // => 'nonsense'
+   */
+  function result(object, property) {
+    var value = object ? object[property] : null;
+    return isFunction(value) ? object[property]() : value;
+  }
+
+  /**
+   * A micro-templating method that handles arbitrary delimiters, preserves
+   * whitespace, and correctly escapes quotes within interpolated code.
+   *
+   * Note: In the development build, `_.template` utilizes sourceURLs for easier
+   * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+   *
+   * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
+   * build and using precompiled templates, or loading Lo-Dash in a sandbox.
+   *
+   * For more information on precompiling templates see:
+   * http://lodash.com/#custom-builds
+   *
+   * For more information on Chrome extension sandboxes see:
+   * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} text The template text.
+   * @param {Obect} data The data object used to populate the text.
+   * @param {Object} options The options object.
+   *  escape - The "escape" delimiter regexp.
+   *  evaluate - The "evaluate" delimiter regexp.
+   *  interpolate - The "interpolate" delimiter regexp.
+   *  sourceURL - The sourceURL of the template's compiled source.
+   *  variable - The data object variable name.
+   *
+   * @returns {Function|String} Returns a compiled function when no `data` object
+   *  is given, else it returns the interpolated text.
+   * @example
+   *
+   * // using a compiled template
+   * var compiled = _.template('hello <%= name %>');
+   * compiled({ 'name': 'moe' });
+   * // => 'hello moe'
+   *
+   * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
+   * _.template(list, { 'people': ['moe', 'larry'] });
+   * // => '<li>moe</li><li>larry</li>'
+   *
+   * // using the "escape" delimiter to escape HTML in data property values
+   * _.template('<b><%- value %></b>', { 'value': '<script>' });
+   * // => '<b>&lt;script&gt;</b>'
+   *
+   * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+   * _.template('hello ${ name }', { 'name': 'curly' });
+   * // => 'hello curly'
+   *
+   * // using the internal `print` function in "evaluate" delimiters
+   * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
+   * // => 'hello stooge!'
+   *
+   * // using custom template delimiters
+   * _.templateSettings = {
+   *   'interpolate': /{{([\s\S]+?)}}/g
+   * };
+   *
+   * _.template('hello {{ name }}!', { 'name': 'mustache' });
+   * // => 'hello mustache!'
+   *
+   * // using the `sourceURL` option to specify a custom sourceURL for the template
+   * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+   * compiled(data);
+   * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+   *
+   * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+   * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+   * compiled.source;
+   * // => function(data) {
+   *   var __t, __p = '', __e = _.escape;
+   *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+   *   return __p;
+   * }
+   *
+   * // using the `source` property to inline compiled templates for meaningful
+   * // line numbers in error messages and a stack trace
+   * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+   *   var JST = {\
+   *     "main": ' + _.template(mainText).source + '\
+   *   };\
+   * ');
+   */
+  function template(text, data, options) {
+    text || (text = '');
+    options = defaults({}, options, lodash.templateSettings);
+
+    var index = 0,
+        source = "__p += '",
+        variable = options.variable;
+
+    var reDelimiters = RegExp(
+      (options.escape || reNoMatch).source + '|' +
+      (options.interpolate || reNoMatch).source + '|' +
+      (options.evaluate || reNoMatch).source + '|$'
+    , 'g');
+
+    text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {
+      source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+      if (escapeValue) {
+        source += "' +\n_.escape(" + escapeValue + ") +\n'";
+      }
+      if (evaluateValue) {
+        source += "';\n" + evaluateValue + ";\n__p += '";
+      }
+      if (interpolateValue) {
+        source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+      }
+      index = offset + match.length;
+      return match;
+    });
+
+    source += "';\n";
+    if (!variable) {
+      variable = 'obj';
+      source = 'with (' + variable + ' || {}) {\n' + source + '\n}\n';
+    }
+    source = 'function(' + variable + ') {\n' +
+      "var __t, __p = '', __j = Array.prototype.join;\n" +
+      "function print() { __p += __j.call(arguments, '') }\n" +
+      source +
+      'return __p\n}';
+
+    try {
+      var result = Function('_', 'return ' + source)(lodash);
+    } catch(e) {
+      e.source = source;
+      throw e;
+    }
+    if (data) {
+      return result(data);
+    }
+    result.source = source;
+    return result;
+  }
+
+  /**
+   * Executes the `callback` function `n` times, returning an array of the results
+   * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
+   * with one argument; (index).
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} n The number of times to execute the callback.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+   * // => [3, 6, 4]
+   *
+   * _.times(3, function(n) { mage.castSpell(n); });
+   * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+   *
+   * _.times(3, function(n) { this.cast(n); }, mage);
+   * // => also calls `mage.castSpell(n)` three times
+   */
+  function times(n, callback, thisArg) {
+    n = +n || 0;
+    var index = -1,
+        result = Array(n);
+
+    while (++index < n) {
+      result[index] = callback.call(thisArg, index);
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.escape`, this method converts the HTML entities
+   * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+   * corresponding characters.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to unescape.
+   * @returns {String} Returns the unescaped string.
+   * @example
+   *
+   * _.unescape('Moe, Larry &amp; Curly');
+   * // => 'Moe, Larry & Curly'
+   */
+  function unescape(string) {
+    return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
+  }
+
+  /**
+   * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} [prefix] The value to prefix the ID with.
+   * @returns {String} Returns the unique ID.
+   * @example
+   *
+   * _.uniqueId('contact_');
+   * // => 'contact_104'
+   *
+   * _.uniqueId();
+   * // => '105'
+   */
+  function uniqueId(prefix) {
+    var id = ++idCounter + '';
+    return prefix ? prefix + id : id;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object that wraps the given `value`.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {Mixed} value The value to wrap.
+   * @returns {Object} Returns the wrapper object.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 },
+   *   { 'name': 'curly', 'age': 60 }
+   * ];
+   *
+   * var youngest = _.chain(stooges)
+   *     .sortBy(function(stooge) { return stooge.age; })
+   *     .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })
+   *     .first();
+   * // => 'moe is 40'
+   */
+  function chain(value) {
+    value = new lodash(value);
+    value.__chain__ = true;
+    return value;
+  }
+
+  /**
+   * Invokes `interceptor` with the `value` as the first argument, and then
+   * returns `value`. The purpose of this method is to "tap into" a method chain,
+   * in order to perform operations on intermediate results within the chain.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {Mixed} value The value to pass to `interceptor`.
+   * @param {Function} interceptor The function to invoke.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * _([1, 2, 3, 4])
+   *  .filter(function(num) { return num % 2 == 0; })
+   *  .tap(alert)
+   *  .map(function(num) { return num * num; })
+   *  .value();
+   * // => // [2, 4] (alerted)
+   * // => [4, 16]
+   */
+  function tap(value, interceptor) {
+    interceptor(value);
+    return value;
+  }
+
+  /**
+   * Enables method chaining on the wrapper object.
+   *
+   * @name chain
+   * @memberOf _
+   * @category Chaining
+   * @returns {Mixed} Returns the wrapper object.
+   * @example
+   *
+   * var sum = _([1, 2, 3])
+   *     .chain()
+   *     .reduce(function(sum, num) { return sum + num; })
+   *     .value()
+   * // => 6`
+   */
+  function wrapperChain() {
+    this.__chain__ = true;
+    return this;
+  }
+
+  /**
+   * Produces the `toString` result of the wrapped value.
+   *
+   * @name toString
+   * @memberOf _
+   * @category Chaining
+   * @returns {String} Returns the string result.
+   * @example
+   *
+   * _([1, 2, 3]).toString();
+   * // => '1,2,3'
+   */
+  function wrapperToString() {
+    return this.__wrapped__ + '';
+  }
+
+  /**
+   * Extracts the wrapped value.
+   *
+   * @name valueOf
+   * @memberOf _
+   * @alias value
+   * @category Chaining
+   * @returns {Mixed} Returns the wrapped value.
+   * @example
+   *
+   * _([1, 2, 3]).valueOf();
+   * // => [1, 2, 3]
+   */
+  function wrapperValueOf() {
+    return this.__wrapped__;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return wrapped values when chaining
+  lodash.after = after;
+  lodash.bind = bind;
+  lodash.bindAll = bindAll;
+  lodash.compact = compact;
+  lodash.compose = compose;
+  lodash.countBy = countBy;
+  lodash.debounce = debounce;
+  lodash.defaults = defaults;
+  lodash.defer = defer;
+  lodash.delay = delay;
+  lodash.difference = difference;
+  lodash.filter = filter;
+  lodash.flatten = flatten;
+  lodash.forEach = forEach;
+  lodash.functions = functions;
+  lodash.groupBy = groupBy;
+  lodash.initial = initial;
+  lodash.intersection = intersection;
+  lodash.invert = invert;
+  lodash.invoke = invoke;
+  lodash.keys = keys;
+  lodash.map = map;
+  lodash.max = max;
+  lodash.memoize = memoize;
+  lodash.min = min;
+  lodash.object = object;
+  lodash.omit = omit;
+  lodash.once = once;
+  lodash.pairs = pairs;
+  lodash.partial = partial;
+  lodash.pick = pick;
+  lodash.pluck = pluck;
+  lodash.range = range;
+  lodash.reject = reject;
+  lodash.rest = rest;
+  lodash.shuffle = shuffle;
+  lodash.sortBy = sortBy;
+  lodash.tap = tap;
+  lodash.throttle = throttle;
+  lodash.times = times;
+  lodash.toArray = toArray;
+  lodash.union = union;
+  lodash.uniq = uniq;
+  lodash.values = values;
+  lodash.where = where;
+  lodash.without = without;
+  lodash.wrap = wrap;
+  lodash.zip = zip;
+
+  // add aliases
+  lodash.collect = map;
+  lodash.drop = rest;
+  lodash.each = forEach;
+  lodash.extend = assign;
+  lodash.methods = functions;
+  lodash.select = filter;
+  lodash.tail = rest;
+  lodash.unique = uniq;
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return unwrapped values when chaining
+  lodash.clone = clone;
+  lodash.contains = contains;
+  lodash.escape = escape;
+  lodash.every = every;
+  lodash.find = find;
+  lodash.findWhere = findWhere;
+  lodash.has = has;
+  lodash.identity = identity;
+  lodash.indexOf = indexOf;
+  lodash.isArguments = isArguments;
+  lodash.isArray = isArray;
+  lodash.isBoolean = isBoolean;
+  lodash.isDate = isDate;
+  lodash.isElement = isElement;
+  lodash.isEmpty = isEmpty;
+  lodash.isEqual = isEqual;
+  lodash.isFinite = isFinite;
+  lodash.isFunction = isFunction;
+  lodash.isNaN = isNaN;
+  lodash.isNull = isNull;
+  lodash.isNumber = isNumber;
+  lodash.isObject = isObject;
+  lodash.isRegExp = isRegExp;
+  lodash.isString = isString;
+  lodash.isUndefined = isUndefined;
+  lodash.lastIndexOf = lastIndexOf;
+  lodash.mixin = mixin;
+  lodash.noConflict = noConflict;
+  lodash.random = random;
+  lodash.reduce = reduce;
+  lodash.reduceRight = reduceRight;
+  lodash.result = result;
+  lodash.size = size;
+  lodash.some = some;
+  lodash.sortedIndex = sortedIndex;
+  lodash.template = template;
+  lodash.unescape = unescape;
+  lodash.uniqueId = uniqueId;
+
+  // add aliases
+  lodash.all = every;
+  lodash.any = some;
+  lodash.detect = find;
+  lodash.foldl = reduce;
+  lodash.foldr = reduceRight;
+  lodash.include = contains;
+  lodash.inject = reduce;
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions capable of returning wrapped and unwrapped values when chaining
+  lodash.first = first;
+  lodash.last = last;
+
+  // add aliases
+  lodash.take = first;
+  lodash.head = first;
+
+  /*--------------------------------------------------------------------------*/
+
+  lodash.chain = chain;
+
+  /**
+   * The semantic version number.
+   *
+   * @static
+   * @memberOf _
+   * @type String
+   */
+  lodash.VERSION = '1.0.1';
+
+  // add functions to `lodash.prototype`
+  mixin(lodash);
+
+  // add "Chaining" functions to the wrapper
+  lodash.prototype.chain = wrapperChain;
+  lodash.prototype.value = wrapperValueOf;
+
+  // add `Array` mutator functions to the wrapper
+  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      var value = this.__wrapped__;
+      func.apply(value, arguments);
+
+      // avoid array-like object bugs with `Array#shift` and `Array#splice`
+      // in Firefox < 10 and IE < 9
+      if (hasObjectSpliceBug && value.length === 0) {
+        delete value[0];
+      }
+      return this;
+    };
+  });
+
+  // add `Array` accessor functions to the wrapper
+  each(['concat', 'join', 'slice'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      var value = this.__wrapped__,
+          result = func.apply(value, arguments);
+
+      if (this.__chain__) {
+        result = new lodash(result);
+        result.__chain__ = true;
+      }
+      return result;
+    };
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  if (freeExports) {
+    // in Node.js or RingoJS v0.8.0+
+    if (freeModule) {
+      (freeModule.exports = lodash)._ = lodash;
+    }
+    // in Narwhal or RingoJS v0.7.0-
+    else {
+      freeExports._ = lodash;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    window._ = lodash;
+  }
+}(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.underscore.min.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.underscore.min.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.underscore.min.js	(revision 533)
@@ -0,0 +1,34 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 (Custom Build) lodash.com/license
+ * Build: `lodash underscore -o ./dist/lodash.underscore.js`
+ * Underscore.js 1.4.4 underscorejs.org/LICENSE
+ */
+;(function(n,t){function r(n,t){var r;if(n&&qt[typeof n])for(r in t||(t=G),n)if(t(n[r],r,n)===tt)break}function e(n,t,r){if(n){t=t&&typeof r=="undefined"?t:a(t,r);var e=n.length;if(r=-1,typeof e=="number")for(;++r<e&&t(n[r],r,n)!==tt;);else for(r in n)if(pt.call(n,r)&&t(n[r],r,n)===tt)break}}function u(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof u?(this.__wrapped__=n,void 0):new u(n)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
+}return r<e?-1:1}function i(n,t,r){function e(){var a=arguments,f=o?this:t;return u||(n=t[i]),r.length&&(a=a.length?(a=p(a),r.concat(a)):r),this instanceof e?(l.prototype=n.prototype,f=new l,l.prototype=K,a=n.apply(f,a),w(a)?a:f):n.apply(f,a)}var u=j(n),o=!r,i=t;return o&&(r=t),u||(t=n),e}function a(n,t,r){if(n==K)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=Dt(n);return function(t){for(var r=u.length,e=L;r--&&(e=t[u[r]]===n[u[r]]););return e}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)
+}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function f(n){return"\\"+It[n]}function c(n){return Mt[n]}function l(){}function p(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function s(n){return $t[n]}function v(n){return vt.call(n)==wt}function h(n){var t,r=[],e=function(n,t){r.push(t)};if(n&&qt[typeof n])for(t in e||(e=G),n)if(pt.call(n,t)&&e(n[t],t,n)===tt)break;
+return r}function g(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]=e[u]}return n}function y(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]==K&&(n[u]=e[u])}return n}function m(n){var t=[];return r(n,function(n,r){j(n)&&t.push(r)}),t.sort()}function _(n){for(var t=-1,r=Dt(n),e=r.length,u={};++t<e;){var o=r[t];u[n[o]]=o}return u}function d(n){if(!n)return J;if(Bt(n)||x(n))return!n.length;for(var t in n)if(pt.call(n,t))return L;
+return J}function b(n,t,e,u){if(n===t)return 0!==n||1/n==1/t;var o=typeof n,i=typeof t;if(n===n&&(!n||"function"!=o&&"object"!=o)&&(!t||"function"!=i&&"object"!=i))return L;if(n==K||t==K)return n===t;if(i=vt.call(n),o=vt.call(t),i!=o)return L;switch(i){case xt:case Et:return+n==+t;case Ot:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Nt:case kt:return n==t+""}if(o=i==At,!o){if(n.__wrapped__||t.__wrapped__)return b(n.__wrapped__||n,t.__wrapped__||t,e,u);if(i!=St)return L;var i=n.constructor,a=t.constructor;
+if(i!=a&&(!j(i)||!(i instanceof i&&j(a)&&a instanceof a)))return L}for(e||(e=[]),u||(u=[]),i=e.length;i--;)if(e[i]==n)return u[i]==t;var f=J,c=0;if(e.push(n),u.push(t),o){if(c=t.length,f=c==n.length)for(;c--&&(f=b(n[c],t[c],e,u)););return f}return r(t,function(t,r,o){return pt.call(o,r)?(c++,!(f=pt.call(n,r)&&b(n[r],t,e,u))&&tt):void 0}),f&&r(n,function(n,t,r){return pt.call(r,t)?!(f=-1<--c)&&tt:void 0}),f}function j(n){return typeof n=="function"}function w(n){return n?qt[typeof n]:L}function A(n){return typeof n=="number"||vt.call(n)==Ot
+}function x(n){return typeof n=="string"||vt.call(n)==kt}function E(n){for(var t=-1,r=Dt(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function O(n,t){var r=L;return typeof(n?n.length:0)=="number"?r=-1<z(n,t):e(n,function(n){return(r=n===t)&&tt}),r}function S(n,t,r){var u=J;if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o&&(u=!!t(n[r],r,n)););}else e(n,function(n,r,e){return!(u=!!t(n,r,e))&&tt});return u}function N(n,t,r){var u=[];if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o;){var i=n[r];
+t(i,r,n)&&u.push(i)}}else e(n,function(n,r,e){t(n,r,e)&&u.push(n)});return u}function k(n,t,r){var e;return t=a(t,r),F(n,function(n,r,u){return t(n,r,u)?(e=n,tt):void 0}),e}function F(n,t,r){if(t&&typeof r=="undefined"&&Bt(n)){r=-1;for(var u=n.length;++r<u&&t(n[r],r,n)!==tt;);}else e(n,t,r)}function R(n,t,r){var u=-1,o=n?n.length:0,i=Array(typeof o=="number"?o:0);if(t=a(t,r),Bt(n))for(;++u<o;)i[u]=t(n[u],u,n);else e(n,function(n,r,e){i[++u]=t(n,r,e)});return i}function T(n,t,r){var u=-1/0,o=u;if(!t&&Bt(n)){r=-1;
+for(var i=n.length;++r<i;){var f=n[r];f>o&&(o=f)}}else t=a(t,r),e(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function q(n,t,r,u){var o=3>arguments.length;if(t=a(t,u,4),Bt(n)){var i=-1,f=n.length;for(o&&(r=n[++i]);++i<f;)r=t(r,n[i],i,n)}else e(n,function(n,e,u){r=o?(o=L,n):t(r,n,e,u)});return r}function I(n,t,r,e){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=Dt(n),u=i.length;return t=a(t,e,4),F(n,function(e,a,f){a=i?i[--u]:--u,r=o?(o=L,n[a]):t(r,n[a],a,f)}),r}function B(n,t,r){var u;
+if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o&&!(u=t(n[r],r,n)););}else e(n,function(n,r,e){return(u=t(n,r,e))&&tt});return!!u}function D(n,t,r){return r&&d(t)?K:(r?k:N)(n,t)}function M(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=-1;for(t=a(t,r);++o<u&&t(n[o],o,n);)e++}else if(e=t,e==K||r)return n[0];return p(n,0,bt(dt(0,e),u))}}function $(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];Bt(o)?st.apply(u,t?o:$(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;
+if(typeof r=="number")e=(0>r?dt(0,u+r):r||0)-1;else if(r)return e=P(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function C(n,t,r){if(typeof t!="number"&&t!=K){var e=0,u=-1,o=n?n.length:0;for(t=a(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==K||r?1:dt(0,t);return p(n,e)}function P(n,t,r,e){var u=0,o=n?n.length:u;for(r=r?a(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function U(n,t,r,e){var u=-1,o=n?n.length:0,i=[],f=i;for(typeof t=="function"&&(e=r,r=t,t=L),r&&(f=[],r=a(r,e));++u<o;){e=n[u];
+var c=r?r(e,u,n):e;(t?!u||f[f.length-1]!==c:0>z(f,c))&&(r&&f.push(c),i.push(e))}return i}function V(n,t){return Ft||ht&&2<arguments.length?ht.call.apply(ht,arguments):i(n,t,p(arguments,2))}function W(n){var r=p(arguments,1);return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){F(m(n),function(t){var r=u[t]=n[t];u.prototype[t]=function(){var n=[this.__wrapped__];return st.apply(n,arguments),n=r.apply(u,n),this.__chain__&&(n=new u(n),n.__chain__=J),n}})}var J=!0,K=null,L=!1,Q=typeof exports=="object"&&exports,X=typeof module=="object"&&module&&module.exports==Q&&module,Y=typeof global=="object"&&global;
+Y.global===Y&&(n=Y);var Z=[],Y={},nt=0,tt=Y,rt=n._,et=/&(?:amp|lt|gt|quot|#39);/g,ut=RegExp("^"+(Y.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ot=/($^)/,it=/[&<>"']/g,at=/['\n\r\t\u2028\u2029\\]/g,ft=Math.ceil,ct=Z.concat,lt=Math.floor,pt=Y.hasOwnProperty,st=Z.push,vt=Y.toString,ht=ut.test(ht=p.bind)&&ht,gt=ut.test(gt=Array.isArray)&&gt,yt=n.isFinite,mt=n.isNaN,_t=ut.test(_t=Object.keys)&&_t,dt=Math.max,bt=Math.min,jt=Math.random,wt="[object Arguments]",At="[object Array]",xt="[object Boolean]",Et="[object Date]",Ot="[object Number]",St="[object Object]",Nt="[object RegExp]",kt="[object String]",Y=!!n.attachEvent,Y=ht&&!/\n|true/.test(ht+Y),Ft=ht&&!Y,Rt=(Rt={0:1,length:1},Z.splice.call(Rt,0,1),Rt[0]),Tt=arguments.constructor==Object,qt={"boolean":L,"function":J,object:J,number:L,string:L,undefined:L},It={"\\":"\\","'":"'","\n":"n","\r":"r","	":"t","\u2028":"u2028","\u2029":"u2029"};
+u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},v(arguments)||(v=function(n){return n?pt.call(n,"callee"):L});var Bt=gt||function(n){return Tt&&n instanceof Array||vt.call(n)==At},Dt=_t?function(n){return w(n)?_t(n):[]}:h,Mt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},$t=_(Mt);j(/x/)&&(j=function(n){return n instanceof Function||"[object Function]"==vt.call(n)});var zt=R;Y&&X&&typeof setImmediate=="function"&&(W=V(setImmediate,n)),u.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0
+}},u.bind=V,u.bindAll=function(n){for(var t=ct.apply(Z,arguments),r=1<t.length?0:(t=m(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=V(n[u],n)}return n},u.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},u.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},u.countBy=function(n,t,r){var e={};return t=a(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",pt.call(e,r)?e[r]++:e[r]=1}),e},u.debounce=function(n,t,r){function e(){a=K,r||(o=n.apply(i,u))
+}var u,o,i,a;return function(){var f=r&&!a;return u=arguments,i=this,clearTimeout(a),a=setTimeout(e,t),f&&(o=n.apply(i,u)),o}},u.defaults=y,u.defer=W,u.delay=function(n,r){var e=p(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},u.difference=function(n){for(var t=-1,r=n.length,e=ct.apply(Z,arguments),u=[];++t<r;){var o=n[t];0>z(e,o,r)&&u.push(o)}return u},u.filter=N,u.flatten=$,u.forEach=F,u.functions=m,u.groupBy=function(n,t,r){var e={};return t=a(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",(pt.call(e,r)?e[r]:e[r]=[]).push(n)
+}),e},u.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else e=t==K||r?1:t||e;return p(n,0,bt(dt(0,u-e),u))},u.intersection=function(n){var t=arguments,r=t.length,e=-1,u=n?n.length:0,o=[];n:for(;++e<u;){var i=n[e];if(0>z(o,i)){for(var a=r;--a;)if(0>z(t[a],i))continue n;o.push(i)}}return o},u.invert=_,u.invoke=function(n,t){var r=p(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);
+return F(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},u.keys=Dt,u.map=R,u.max=T,u.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return pt.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},u.min=function(n,t,r){var u=1/0,o=u;if(!t&&Bt(n)){r=-1;for(var i=n.length;++r<i;){var f=n[r];f<o&&(o=f)}}else t=a(t,r),e(n,function(n,r,e){r=t(n,r,e),r<u&&(u=r,o=n)});return o},u.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]
+}return u},u.omit=function(n){var t=ct.apply(Z,arguments),e={};return r(n,function(n,r){0>z(t,r,1)&&(e[r]=n)}),e},u.once=function(n){var t,r;return function(){return t?r:(t=J,r=n.apply(this,arguments),n=K,r)}},u.pairs=function(n){for(var t=-1,r=Dt(n),e=r.length,u=Array(e);++t<e;){var o=r[t];u[t]=[o,n[o]]}return u},u.partial=function(n){return i(n,p(arguments,1))},u.pick=function(n){for(var t=0,r=ct.apply(Z,arguments),e=r.length,u={};++t<e;){var o=r[t];o in n&&(u[o]=n[o])}return u},u.pluck=zt,u.range=function(n,t,r){n=+n||0,r=+r||1,t==K&&(t=n,n=0);
+var e=-1;t=dt(0,ft((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},u.reject=function(n,t,r){return t=a(t,r),N(n,function(n,r,e){return!t(n,r,e)})},u.rest=C,u.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return F(n,function(n){var r=lt(jt()*(++t+1));e[t]=e[r],e[r]=n}),e},u.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=a(t,r),F(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i
+},u.tap=function(n,t){return t(n),n},u.throttle=function(n,t){function r(){a=new Date,i=K,u=n.apply(o,e)}var e,u,o,i,a=0;return function(){var f=new Date,c=t-(f-a);return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=K,a=f,u=n.apply(o,e)),u}},u.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},u.toArray=function(n){return n&&typeof n.length=="number"?p(n):E(n)},u.union=function(){return U(ct.apply(Z,arguments))},u.uniq=U,u.values=E,u.where=D,u.without=function(n){for(var t=-1,r=n.length,e=[];++t<r;){var u=n[t];
+0>z(arguments,u,1)&&e.push(u)}return e},u.wrap=function(n,t){return function(){var r=[n];return st.apply(r,arguments),t.apply(this,r)}},u.zip=function(n){for(var t=-1,r=n?T(zt(arguments,"length")):0,e=Array(r);++t<r;)e[t]=zt(arguments,t);return e},u.collect=R,u.drop=C,u.each=F,u.extend=g,u.methods=m,u.select=N,u.tail=C,u.unique=U,u.clone=function(n){return w(n)?Bt(n)?p(n):g({},n):n},u.contains=O,u.escape=function(n){return n==K?"":(n+"").replace(it,c)},u.every=S,u.find=k,u.findWhere=function(n,t){return D(n,t,J)
+},u.has=function(n,t){return n?pt.call(n,t):L},u.identity=G,u.indexOf=z,u.isArguments=v,u.isArray=Bt,u.isBoolean=function(n){return n===J||n===L||vt.call(n)==xt},u.isDate=function(n){return n instanceof Date||vt.call(n)==Et},u.isElement=function(n){return n?1===n.nodeType:L},u.isEmpty=d,u.isEqual=b,u.isFinite=function(n){return yt(n)&&!mt(parseFloat(n))},u.isFunction=j,u.isNaN=function(n){return A(n)&&n!=+n},u.isNull=function(n){return n===K},u.isNumber=A,u.isObject=w,u.isRegExp=function(n){return n instanceof RegExp||vt.call(n)==Nt
+},u.isString=x,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?dt(0,e+r):bt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=H,u.noConflict=function(){return n._=rt,this},u.random=function(n,t){return n==K&&t==K&&(t=1),n=+n||0,t==K&&(t=n,n=0),n+lt(jt()*((+t||0)-n+1))},u.reduce=q,u.reduceRight=I,u.result=function(n,t){var r=n?n[t]:K;return j(r)?n[t]():r},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Dt(n).length
+},u.some=B,u.sortedIndex=P,u.template=function(n,t,r){n||(n=""),r=y({},r,u.templateSettings);var e=0,o="__p+='",i=r.variable;n.replace(RegExp((r.escape||ot).source+"|"+(r.interpolate||ot).source+"|"+(r.evaluate||ot).source+"|$","g"),function(t,r,u,i,a){return o+=n.slice(e,a).replace(at,f),r&&(o+="'+_['escape']("+r+")+'"),i&&(o+="';"+i+";__p+='"),u&&(o+="'+((__t=("+u+"))==null?'':__t)+'"),e=a+t.length,t}),o+="';\n",i||(i="obj",o="with("+i+"||{}){"+o+"}"),o="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+o+"return __p}";
+try{var a=Function("_","return "+o)(u)}catch(c){throw c.source=o,c}return t?a(t):(a.source=o,a)},u.unescape=function(n){return n==K?"":(n+"").replace(et,s)},u.uniqueId=function(n){var t=++nt+"";return n?n+t:t},u.all=S,u.any=B,u.detect=k,u.foldl=q,u.foldr=I,u.include=O,u.inject=q,u.first=M,u.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==K||r)return n[u-1];return p(n,dt(0,u-e))}},u.take=M,u.head=M,u.chain=function(n){return n=new u(n),n.__chain__=J,n
+},u.VERSION="1.0.1",H(u),u.prototype.chain=function(){return this.__chain__=J,this},u.prototype.value=function(){return this.__wrapped__},e("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Z[n];u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Rt&&0===n.length&&delete n[0],this}}),e(["concat","join","slice"],function(n){var t=Z[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new u(n),n.__chain__=J),n
+}}),Q?X?(X.exports=u)._=u:Q._=u:n._=u})(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/doc/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/doc/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/doc/README.md	(revision 533)
@@ -0,0 +1,3590 @@
+# Lo-Dash <sup>v1.0.1</sup>
+
+<!-- div -->
+
+
+<!-- div -->
+
+## <a id="Arrays"></a>`Arrays`
+* [`_.compact`](#_compactarray)
+* [`_.difference`](#_differencearray--array1-array2-)
+* [`_.drop`](#_restarray--callbackn1-thisarg)
+* [`_.first`](#_firstarray--callbackn-thisarg)
+* [`_.flatten`](#_flattenarray-shallow)
+* [`_.head`](#_firstarray--callbackn-thisarg)
+* [`_.indexOf`](#_indexofarray-value--fromindex0)
+* [`_.initial`](#_initialarray--callbackn1-thisarg)
+* [`_.intersection`](#_intersectionarray1-array2-)
+* [`_.last`](#_lastarray--callbackn-thisarg)
+* [`_.lastIndexOf`](#_lastindexofarray-value--fromindexarraylength-1)
+* [`_.object`](#_objectkeys--values)
+* [`_.range`](#_rangestart0-end--step1)
+* [`_.rest`](#_restarray--callbackn1-thisarg)
+* [`_.sortedIndex`](#_sortedindexarray-value--callbackidentity-thisarg)
+* [`_.tail`](#_restarray--callbackn1-thisarg)
+* [`_.take`](#_firstarray--callbackn-thisarg)
+* [`_.union`](#_unionarray1-array2-)
+* [`_.uniq`](#_uniqarray--issortedfalse-callbackidentity-thisarg)
+* [`_.unique`](#_uniqarray--issortedfalse-callbackidentity-thisarg)
+* [`_.without`](#_withoutarray--value1-value2-)
+* [`_.zip`](#_ziparray1-array2-)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Chaining`
+* [`_`](#_value)
+* [`_.tap`](#_tapvalue-interceptor)
+* [`_.prototype.toString`](#_prototypetostring)
+* [`_.prototype.value`](#_prototypevalueof)
+* [`_.prototype.valueOf`](#_prototypevalueof)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Collections`
+* [`_.all`](#_everycollection--callbackidentity-thisarg)
+* [`_.any`](#_somecollection--callbackidentity-thisarg)
+* [`_.at`](#_atcollection--index1-index2-)
+* [`_.collect`](#_mapcollection--callbackidentity-thisarg)
+* [`_.contains`](#_containscollection-target--fromindex0)
+* [`_.countBy`](#_countbycollection--callbackidentity-thisarg)
+* [`_.detect`](#_findcollection--callbackidentity-thisarg)
+* [`_.each`](#_foreachcollection--callbackidentity-thisarg)
+* [`_.every`](#_everycollection--callbackidentity-thisarg)
+* [`_.filter`](#_filtercollection--callbackidentity-thisarg)
+* [`_.find`](#_findcollection--callbackidentity-thisarg)
+* [`_.foldl`](#_reducecollection--callbackidentity-accumulator-thisarg)
+* [`_.foldr`](#_reducerightcollection--callbackidentity-accumulator-thisarg)
+* [`_.forEach`](#_foreachcollection--callbackidentity-thisarg)
+* [`_.groupBy`](#_groupbycollection--callbackidentity-thisarg)
+* [`_.include`](#_containscollection-target--fromindex0)
+* [`_.inject`](#_reducecollection--callbackidentity-accumulator-thisarg)
+* [`_.invoke`](#_invokecollection-methodname--arg1-arg2-)
+* [`_.map`](#_mapcollection--callbackidentity-thisarg)
+* [`_.max`](#_maxcollection--callbackidentity-thisarg)
+* [`_.min`](#_mincollection--callbackidentity-thisarg)
+* [`_.pluck`](#_pluckcollection-property)
+* [`_.reduce`](#_reducecollection--callbackidentity-accumulator-thisarg)
+* [`_.reduceRight`](#_reducerightcollection--callbackidentity-accumulator-thisarg)
+* [`_.reject`](#_rejectcollection--callbackidentity-thisarg)
+* [`_.select`](#_filtercollection--callbackidentity-thisarg)
+* [`_.shuffle`](#_shufflecollection)
+* [`_.size`](#_sizecollection)
+* [`_.some`](#_somecollection--callbackidentity-thisarg)
+* [`_.sortBy`](#_sortbycollection--callbackidentity-thisarg)
+* [`_.toArray`](#_toarraycollection)
+* [`_.where`](#_wherecollection-properties)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Functions`
+* [`_.after`](#_aftern-func)
+* [`_.bind`](#_bindfunc--thisarg-arg1-arg2-)
+* [`_.bindAll`](#_bindallobject--methodname1-methodname2-)
+* [`_.bindKey`](#_bindkeyobject-key--arg1-arg2-)
+* [`_.compose`](#_composefunc1-func2-)
+* [`_.debounce`](#_debouncefunc-wait-immediate)
+* [`_.defer`](#_deferfunc--arg1-arg2-)
+* [`_.delay`](#_delayfunc-wait--arg1-arg2-)
+* [`_.memoize`](#_memoizefunc--resolver)
+* [`_.once`](#_oncefunc)
+* [`_.partial`](#_partialfunc--arg1-arg2-)
+* [`_.partialRight`](#_partialrightfunc--arg1-arg2-)
+* [`_.throttle`](#_throttlefunc-wait)
+* [`_.wrap`](#_wrapvalue-wrapper)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Objects`
+* [`_.assign`](#_assignobject--source1-source2--callback-thisarg)
+* [`_.clone`](#_clonevalue--deepfalse-callback-thisarg)
+* [`_.cloneDeep`](#_clonedeepvalue--callback-thisarg)
+* [`_.defaults`](#_defaultsobject--source1-source2-)
+* [`_.extend`](#_assignobject--source1-source2--callback-thisarg)
+* [`_.forIn`](#_forinobject--callbackidentity-thisarg)
+* [`_.forOwn`](#_forownobject--callbackidentity-thisarg)
+* [`_.functions`](#_functionsobject)
+* [`_.has`](#_hasobject-property)
+* [`_.invert`](#_invertobject)
+* [`_.isArguments`](#_isargumentsvalue)
+* [`_.isArray`](#_isarrayvalue)
+* [`_.isBoolean`](#_isbooleanvalue)
+* [`_.isDate`](#_isdatevalue)
+* [`_.isElement`](#_iselementvalue)
+* [`_.isEmpty`](#_isemptyvalue)
+* [`_.isEqual`](#_isequala-b--callback-thisarg)
+* [`_.isFinite`](#_isfinitevalue)
+* [`_.isFunction`](#_isfunctionvalue)
+* [`_.isNaN`](#_isnanvalue)
+* [`_.isNull`](#_isnullvalue)
+* [`_.isNumber`](#_isnumbervalue)
+* [`_.isObject`](#_isobjectvalue)
+* [`_.isPlainObject`](#_isplainobjectvalue)
+* [`_.isRegExp`](#_isregexpvalue)
+* [`_.isString`](#_isstringvalue)
+* [`_.isUndefined`](#_isundefinedvalue)
+* [`_.keys`](#_keysobject)
+* [`_.merge`](#_mergeobject--source1-source2--callback-thisarg)
+* [`_.methods`](#_functionsobject)
+* [`_.omit`](#_omitobject-callback-prop1-prop2--thisarg)
+* [`_.pairs`](#_pairsobject)
+* [`_.pick`](#_pickobject-callback-prop1-prop2--thisarg)
+* [`_.values`](#_valuesobject)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Utilities`
+* [`_.escape`](#_escapestring)
+* [`_.identity`](#_identityvalue)
+* [`_.mixin`](#_mixinobject)
+* [`_.noConflict`](#_noconflict)
+* [`_.random`](#_randommin0-max1)
+* [`_.result`](#_resultobject-property)
+* [`_.template`](#_templatetext-data-options)
+* [`_.times`](#_timesn-callback--thisarg)
+* [`_.unescape`](#_unescapestring)
+* [`_.uniqueId`](#_uniqueidprefix)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Methods`
+* [`_.templateSettings.imports._`](#_templatesettingsimports_)
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Properties`
+* [`_.VERSION`](#_version)
+* [`_.templateSettings`](#_templatesettings)
+* [`_.templateSettings.escape`](#_templatesettingsescape)
+* [`_.templateSettings.evaluate`](#_templatesettingsevaluate)
+* [`_.templateSettings.interpolate`](#_templatesettingsinterpolate)
+* [`_.templateSettings.variable`](#_templatesettingsvariable)
+* [`_.templateSettings.imports`](#_templatesettingsimports)
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+
+<!-- div -->
+
+## `âArraysâ Methods`
+
+<!-- div -->
+
+### <a id="_compactarray"></a>`_.compact(array)`
+<a href="#_compactarray">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3166 "View in source") [&#x24C9;][1]
+
+Creates an array with all falsey values of `array` removed. The values `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+
+#### Arguments
+1. `array` *(Array)*: The array to compact.
+
+#### Returns
+*(Array)*: Returns a new filtered array.
+
+#### Example
+```js
+_.compact([0, 1, false, 2, '', 3]);
+// => [1, 2, 3]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_differencearray--array1-array2-"></a>`_.difference(array [, array1, array2, ...])`
+<a href="#_differencearray--array1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3196 "View in source") [&#x24C9;][1]
+
+Creates an array of `array` elements not present in the other arrays using strict equality for comparisons, i.e. `===`.
+
+#### Arguments
+1. `array` *(Array)*: The array to process.
+2. `[array1, array2, ...]` *(Array)*: Arrays to check.
+
+#### Returns
+*(Array)*: Returns a new array of `array` elements not present in the  other arrays.
+
+#### Example
+```js
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+// => [1, 3, 4]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_firstarray--callbackn-thisarg"></a>`_.first(array [, callback|n, thisArg])`
+<a href="#_firstarray--callbackn-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3268 "View in source") [&#x24C9;][1]
+
+Gets the first element of the `array`. If a number `n` is passed, the first `n` elements of the `array` are returned. If a `callback` function is passed, the first elements the `callback` returns truthy for are returned. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, array)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*head, take*
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[callback|n]` *(Function|Object|Number|String)*: The function called per element or the number of elements to return. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the first element(s) of `array`.
+
+#### Example
+```js
+_.first([1, 2, 3]);
+// => 1
+
+_.first([1, 2, 3], 2);
+// => [1, 2]
+
+_.first([1, 2, 3], function(num) {
+  return num < 3;
+});
+// => [1, 2]
+
+var food = [
+  { 'name': 'banana', 'organic': true },
+  { 'name': 'beet',   'organic': false },
+];
+
+// using "_.pluck" callback shorthand
+_.first(food, 'organic');
+// => [{ 'name': 'banana', 'organic': true }]
+
+var food = [
+  { 'name': 'apple',  'type': 'fruit' },
+  { 'name': 'banana', 'type': 'fruit' },
+  { 'name': 'beet',   'type': 'vegetable' }
+];
+
+// using "_.where" callback shorthand
+_.first(food, { 'type': 'fruit' });
+// => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_flattenarray-shallow"></a>`_.flatten(array, shallow)`
+<a href="#_flattenarray-shallow">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3307 "View in source") [&#x24C9;][1]
+
+Flattens a nested array *(the nesting can be to any depth)*. If `shallow` is truthy, `array` will only be flattened a single level.
+
+#### Arguments
+1. `array` *(Array)*: The array to compact.
+2. `shallow` *(Boolean)*: A flag to indicate only flattening a single level.
+
+#### Returns
+*(Array)*: Returns a new flattened array.
+
+#### Example
+```js
+_.flatten([1, [2], [3, [[4]]]]);
+// => [1, 2, 3, 4];
+
+_.flatten([1, [2], [3, [[4]]]], true);
+// => [1, 2, 3, [[4]]];
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_indexofarray-value--fromindex0"></a>`_.indexOf(array, value [, fromIndex=0])`
+<a href="#_indexofarray-value--fromindex0">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3349 "View in source") [&#x24C9;][1]
+
+Gets the index at which the first occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` for `fromIndex` will run a faster binary search.
+
+#### Arguments
+1. `array` *(Array)*: The array to search.
+2. `value` *(Mixed)*: The value to search for.
+3. `[fromIndex=0]` *(Boolean|Number)*: The index to search from or `true` to perform a binary search on a sorted `array`.
+
+#### Returns
+*(Number)*: Returns the index of the matched value or `-1`.
+
+#### Example
+```js
+_.indexOf([1, 2, 3, 1, 2, 3], 2);
+// => 1
+
+_.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+// => 4
+
+_.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+// => 2
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_initialarray--callbackn1-thisarg"></a>`_.initial(array [, callback|n=1, thisArg])`
+<a href="#_initialarray--callbackn1-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3423 "View in source") [&#x24C9;][1]
+
+Gets all but the last element of `array`. If a number `n` is passed, the last `n` elements are excluded from the result. If a `callback` function is passed, the last elements the `callback` returns truthy for are excluded from the result. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, array)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[callback|n=1]` *(Function|Object|Number|String)*: The function called per element or the number of elements to exclude. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a slice of `array`.
+
+#### Example
+```js
+_.initial([1, 2, 3]);
+// => [1, 2]
+
+_.initial([1, 2, 3], 2);
+// => [1]
+
+_.initial([1, 2, 3], function(num) {
+  return num > 1;
+});
+// => [1]
+
+var food = [
+  { 'name': 'beet',   'organic': false },
+  { 'name': 'carrot', 'organic': true }
+];
+
+// using "_.pluck" callback shorthand
+_.initial(food, 'organic');
+// => [{ 'name': 'beet',   'organic': false }]
+
+var food = [
+  { 'name': 'banana', 'type': 'fruit' },
+  { 'name': 'beet',   'type': 'vegetable' },
+  { 'name': 'carrot', 'type': 'vegetable' }
+];
+
+// using "_.where" callback shorthand
+_.initial(food, { 'type': 'vegetable' });
+// => [{ 'name': 'banana', 'type': 'fruit' }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_intersectionarray1-array2-"></a>`_.intersection([array1, array2, ...])`
+<a href="#_intersectionarray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3457 "View in source") [&#x24C9;][1]
+
+Computes the intersection of all the passed-in arrays using strict equality for comparisons, i.e. `===`.
+
+#### Arguments
+1. `[array1, array2, ...]` *(Array)*: Arrays to process.
+
+#### Returns
+*(Array)*: Returns a new array of unique elements that are present  in **all** of the arrays.
+
+#### Example
+```js
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+// => [1, 2]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_lastarray--callbackn-thisarg"></a>`_.last(array [, callback|n, thisArg])`
+<a href="#_lastarray--callbackn-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3548 "View in source") [&#x24C9;][1]
+
+Gets the last element of the `array`. If a number `n` is passed, the last `n` elements of the `array` are returned. If a `callback` function is passed, the last elements the `callback` returns truthy for are returned. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, array)*.
+
+ If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[callback|n]` *(Function|Object|Number|String)*: The function called per element or the number of elements to return. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the last element(s) of `array`.
+
+#### Example
+```js
+_.last([1, 2, 3]);
+// => 3
+
+_.last([1, 2, 3], 2);
+// => [2, 3]
+
+_.last([1, 2, 3], function(num) {
+  return num > 1;
+});
+// => [2, 3]
+
+var food = [
+  { 'name': 'beet',   'organic': false },
+  { 'name': 'carrot', 'organic': true }
+];
+
+// using "_.pluck" callback shorthand
+_.last(food, 'organic');
+// => [{ 'name': 'carrot', 'organic': true }]
+
+var food = [
+  { 'name': 'banana', 'type': 'fruit' },
+  { 'name': 'beet',   'type': 'vegetable' },
+  { 'name': 'carrot', 'type': 'vegetable' }
+];
+
+// using "_.where" callback shorthand
+_.last(food, { 'type': 'vegetable' });
+// => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_lastindexofarray-value--fromindexarraylength-1"></a>`_.lastIndexOf(array, value [, fromIndex=array.length-1])`
+<a href="#_lastindexofarray-value--fromindexarraylength-1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3589 "View in source") [&#x24C9;][1]
+
+Gets the index at which the last occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the offset from the end of the collection.
+
+#### Arguments
+1. `array` *(Array)*: The array to search.
+2. `value` *(Mixed)*: The value to search for.
+3. `[fromIndex=array.length-1]` *(Number)*: The index to search from.
+
+#### Returns
+*(Number)*: Returns the index of the matched value or `-1`.
+
+#### Example
+```js
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+// => 4
+
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+// => 1
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_objectkeys--values"></a>`_.object(keys [, values=[]])`
+<a href="#_objectkeys--values">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3619 "View in source") [&#x24C9;][1]
+
+Creates an object composed from arrays of `keys` and `values`. Pass either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or two arrays, one of `keys` and one of corresponding `values`.
+
+#### Arguments
+1. `keys` *(Array)*: The array of keys.
+2. `[values=[]]` *(Array)*: The array of values.
+
+#### Returns
+*(Object)*: Returns an object composed of the given keys and  corresponding values.
+
+#### Example
+```js
+_.object(['moe', 'larry'], [30, 40]);
+// => { 'moe': 30, 'larry': 40 }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_rangestart0-end--step1"></a>`_.range([start=0], end [, step=1])`
+<a href="#_rangestart0-end--step1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3663 "View in source") [&#x24C9;][1]
+
+Creates an array of numbers *(positive and/or negative)* progressing from `start` up to but not including `end`.
+
+#### Arguments
+1. `[start=0]` *(Number)*: The start of the range.
+2. `end` *(Number)*: The end of the range.
+3. `[step=1]` *(Number)*: The value to increment or descrement by.
+
+#### Returns
+*(Array)*: Returns a new range array.
+
+#### Example
+```js
+_.range(10);
+// => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+_.range(1, 11);
+// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+_.range(0, 30, 5);
+// => [0, 5, 10, 15, 20, 25]
+
+_.range(0, -10, -1);
+// => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+
+_.range(0);
+// => []
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_restarray--callbackn1-thisarg"></a>`_.rest(array [, callback|n=1, thisArg])`
+<a href="#_restarray--callbackn1-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3741 "View in source") [&#x24C9;][1]
+
+The opposite of `_.initial`, this method gets all but the first value of `array`. If a number `n` is passed, the first `n` values are excluded from the result. If a `callback` function is passed, the first elements the `callback` returns truthy for are excluded from the result. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, array)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*drop, tail*
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[callback|n=1]` *(Function|Object|Number|String)*: The function called per element or the number of elements to exclude. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a slice of `array`.
+
+#### Example
+```js
+_.rest([1, 2, 3]);
+// => [2, 3]
+
+_.rest([1, 2, 3], 2);
+// => [3]
+
+_.rest([1, 2, 3], function(num) {
+  return num < 3;
+});
+// => [3]
+
+var food = [
+  { 'name': 'banana', 'organic': true },
+  { 'name': 'beet',   'organic': false },
+];
+
+// using "_.pluck" callback shorthand
+_.rest(food, 'organic');
+// => [{ 'name': 'beet', 'organic': false }]
+
+var food = [
+  { 'name': 'apple',  'type': 'fruit' },
+  { 'name': 'banana', 'type': 'fruit' },
+  { 'name': 'beet',   'type': 'vegetable' }
+];
+
+// using "_.where" callback shorthand
+_.rest(food, { 'type': 'fruit' });
+// => [{ 'name': 'beet', 'type': 'vegetable' }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_sortedindexarray-value--callbackidentity-thisarg"></a>`_.sortedIndex(array, value [, callback=identity, thisArg])`
+<a href="#_sortedindexarray-value--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3805 "View in source") [&#x24C9;][1]
+
+Uses a binary search to determine the smallest index at which the `value` should be inserted into `array` in order to maintain the sort order of the sorted `array`. If `callback` is passed, it will be executed for `value` and each element in `array` to compute their sort ranking. The `callback` is bound to `thisArg` and invoked with one argument; *(value)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `array` *(Array)*: The array to iterate over.
+2. `value` *(Mixed)*: The value to evaluate.
+3. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Number)*: Returns the index at which the value should be inserted  into `array`.
+
+#### Example
+```js
+_.sortedIndex([20, 30, 50], 40);
+// => 2
+
+// using "_.pluck" callback shorthand
+_.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+// => 2
+
+var dict = {
+  'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+};
+
+_.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+  return dict.wordToNumber[word];
+});
+// => 2
+
+_.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+  return this.wordToNumber[word];
+}, dict);
+// => 2
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_unionarray1-array2-"></a>`_.union([array1, array2, ...])`
+<a href="#_unionarray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3837 "View in source") [&#x24C9;][1]
+
+Computes the union of the passed-in arrays using strict equality for comparisons, i.e. `===`.
+
+#### Arguments
+1. `[array1, array2, ...]` *(Array)*: Arrays to process.
+
+#### Returns
+*(Array)*: Returns a new array of unique values, in order, that are  present in one or more of the arrays.
+
+#### Example
+```js
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+// => [1, 2, 3, 101, 10]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_uniqarray--issortedfalse-callbackidentity-thisarg"></a>`_.uniq(array [, isSorted=false, callback=identity, thisArg])`
+<a href="#_uniqarray--issortedfalse-callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3884 "View in source") [&#x24C9;][1]
+
+Creates a duplicate-value-free version of the `array` using strict equality for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` for `isSorted` will run a faster algorithm. If `callback` is passed, each element of `array` is passed through a callback` before uniqueness is computed. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, array)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*unique*
+
+#### Arguments
+1. `array` *(Array)*: The array to process.
+2. `[isSorted=false]` *(Boolean)*: A flag to indicate that the `array` is already sorted.
+3. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a duplicate-value-free array.
+
+#### Example
+```js
+_.uniq([1, 2, 1, 3, 1]);
+// => [1, 2, 3]
+
+_.uniq([1, 1, 2, 2, 3], true);
+// => [1, 2, 3]
+
+_.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
+// => [1, 2, 3]
+
+_.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
+// => [1, 2, 3]
+
+// using "_.pluck" callback shorthand
+_.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+// => [{ 'x': 1 }, { 'x': 2 }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_withoutarray--value1-value2-"></a>`_.without(array [, value1, value2, ...])`
+<a href="#_withoutarray--value1-value2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3943 "View in source") [&#x24C9;][1]
+
+Creates an array with all occurrences of the passed values removed using strict equality for comparisons, i.e. `===`.
+
+#### Arguments
+1. `array` *(Array)*: The array to filter.
+2. `[value1, value2, ...]` *(Mixed)*: Values to remove.
+
+#### Returns
+*(Array)*: Returns a new filtered array.
+
+#### Example
+```js
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+// => [2, 3, 4]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_ziparray1-array2-"></a>`_.zip([array1, array2, ...])`
+<a href="#_ziparray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3974 "View in source") [&#x24C9;][1]
+
+Groups the elements of each array at their corresponding indexes. Useful for separate data sources that are coordinated through matching array indexes. For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix in a similar fashion.
+
+#### Arguments
+1. `[array1, array2, ...]` *(Array)*: Arrays to process.
+
+#### Returns
+*(Array)*: Returns a new array of grouped elements.
+
+#### Example
+```js
+_.zip(['moe', 'larry'], [30, 40], [true, false]);
+// => [['moe', 30, true], ['larry', 40, false]]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `âChainingâ Methods`
+
+<!-- div -->
+
+### <a id="_value"></a>`_(value)`
+<a href="#_value">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L272 "View in source") [&#x24C9;][1]
+
+Creates a `lodash` object, that wraps the given `value`, to enable method chaining.
+
+In addition to Lo-Dash methods, wrappers also have the following `Array` methods:<br>
+`concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, and `unshift`
+
+The chainable wrapper functions are:<br>
+`after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`, `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
+
+The non-chainable wrapper functions are:<br>
+`clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
+
+The wrapper functions `first` and `last` return wrapped values when `n` is passed, otherwise they return unwrapped values.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to wrap in a `lodash` instance.
+
+#### Returns
+*(Object)*: Returns a `lodash` instance.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_tapvalue-interceptor"></a>`_.tap(value, interceptor)`
+<a href="#_tapvalue-interceptor">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4874 "View in source") [&#x24C9;][1]
+
+Invokes `interceptor` with the `value` as the first argument, and then returns `value`. The purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to pass to `interceptor`.
+2. `interceptor` *(Function)*: The function to invoke.
+
+#### Returns
+*(Mixed)*: Returns `value`.
+
+#### Example
+```js
+_([1, 2, 3, 4])
+ .filter(function(num) { return num % 2 == 0; })
+ .tap(alert)
+ .map(function(num) { return num * num; })
+ .value();
+// => // [2, 4] (alerted)
+// => [4, 16]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_prototypetostring"></a>`_.prototype.toString()`
+<a href="#_prototypetostring">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4891 "View in source") [&#x24C9;][1]
+
+Produces the `toString` result of the wrapped value.
+
+#### Returns
+*(String)*: Returns the string result.
+
+#### Example
+```js
+_([1, 2, 3]).toString();
+// => '1,2,3'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_prototypevalueof"></a>`_.prototype.valueOf()`
+<a href="#_prototypevalueof">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4908 "View in source") [&#x24C9;][1]
+
+Extracts the wrapped value.
+
+#### Aliases
+*value*
+
+#### Returns
+*(Mixed)*: Returns the wrapped value.
+
+#### Example
+```js
+_([1, 2, 3]).valueOf();
+// => [1, 2, 3]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `âCollectionsâ Methods`
+
+<!-- div -->
+
+### <a id="_atcollection--index1-index2-"></a>`_.at(collection [, index1, index2, ...])`
+<a href="#_atcollection--index1-index2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2167 "View in source") [&#x24C9;][1]
+
+Creates an array of elements from the specified indexes, or keys, of the `collection`. Indexes may be specified as individual arguments or as arrays of indexes.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[index1, index2, ...]` *(Array|Number|String)*: The indexes of `collection` to retrieve, either as individual arguments or arrays.
+
+#### Returns
+*(Array)*: Returns a new array of elements corresponding to the  provided indexes.
+
+#### Example
+```js
+_.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+// => ['a', 'c', 'e']
+
+_.at(['moe', 'larry', 'curly'], 0, 2);
+// => ['moe', 'curly']
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_containscollection-target--fromindex0"></a>`_.contains(collection, target [, fromIndex=0])`
+<a href="#_containscollection-target--fromindex0">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2209 "View in source") [&#x24C9;][1]
+
+Checks if a given `target` element is present in a `collection` using strict equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the offset from the end of the collection.
+
+#### Aliases
+*include*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `target` *(Mixed)*: The value to check for.
+3. `[fromIndex=0]` *(Number)*: The index to search from.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `target` element is found, else `false`.
+
+#### Example
+```js
+_.contains([1, 2, 3], 1);
+// => true
+
+_.contains([1, 2, 3], 1, 2);
+// => false
+
+_.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+// => true
+
+_.contains('curly', 'ur');
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_countbycollection--callbackidentity-thisarg"></a>`_.countBy(collection [, callback=identity, thisArg])`
+<a href="#_countbycollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2263 "View in source") [&#x24C9;][1]
+
+Creates an object composed of keys returned from running each element of the `collection` through the given `callback`. The corresponding value of each key is the number of times the key was returned by the `callback`. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns the composed aggregate object.
+
+#### Example
+```js
+_.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+// => { '4': 1, '6': 2 }
+
+_.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+// => { '4': 1, '6': 2 }
+
+_.countBy(['one', 'two', 'three'], 'length');
+// => { '3': 2, '5': 1 }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_everycollection--callbackidentity-thisarg"></a>`_.every(collection [, callback=identity, thisArg])`
+<a href="#_everycollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2315 "View in source") [&#x24C9;][1]
+
+Checks if the `callback` returns a truthy value for **all** elements of a `collection`. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*all*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Boolean)*: Returns `true` if all elements pass the callback check,  else `false`.
+
+#### Example
+```js
+_.every([true, 1, null, 'yes'], Boolean);
+// => false
+
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+// using "_.pluck" callback shorthand
+_.every(stooges, 'age');
+// => true
+
+// using "_.where" callback shorthand
+_.every(stooges, { 'age': 50 });
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_filtercollection--callbackidentity-thisarg"></a>`_.filter(collection [, callback=identity, thisArg])`
+<a href="#_filtercollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2376 "View in source") [&#x24C9;][1]
+
+Examines each element in a `collection`, returning an array of all elements the `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*select*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a new array of elements that passed the callback check.
+
+#### Example
+```js
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+// => [2, 4, 6]
+
+var food = [
+  { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+  { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+];
+
+// using "_.pluck" callback shorthand
+_.filter(food, 'organic');
+// => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+
+// using "_.where" callback shorthand
+_.filter(food, { 'type': 'fruit' });
+// => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_findcollection--callbackidentity-thisarg"></a>`_.find(collection [, callback=identity, thisArg])`
+<a href="#_findcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2443 "View in source") [&#x24C9;][1]
+
+Examines each element in a `collection`, returning the first that the `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*detect*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the element that passed the callback check,  else `undefined`.
+
+#### Example
+```js
+var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+// => 2
+
+var food = [
+  { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+  { 'name': 'banana', 'organic': true,  'type': 'fruit' },
+  { 'name': 'beet',   'organic': false, 'type': 'vegetable' },
+  { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+];
+
+// using "_.where" callback shorthand
+var veggie = _.find(food, { 'type': 'vegetable' });
+// => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
+
+// using "_.pluck" callback shorthand
+var healthy = _.find(food, 'organic');
+// => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_foreachcollection--callbackidentity-thisarg"></a>`_.forEach(collection [, callback=identity, thisArg])`
+<a href="#_foreachcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2478 "View in source") [&#x24C9;][1]
+
+Iterates over a `collection`, executing the `callback` for each element in the `collection`. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*. Callbacks may exit iteration early by explicitly returning `false`.
+
+#### Aliases
+*each*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array, Object, String)*: Returns `collection`.
+
+#### Example
+```js
+_([1, 2, 3]).forEach(alert).join(',');
+// => alerts each number and returns '1,2,3'
+
+_.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
+// => alerts each number value (order is not guaranteed)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_groupbycollection--callbackidentity-thisarg"></a>`_.groupBy(collection [, callback=identity, thisArg])`
+<a href="#_groupbycollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2528 "View in source") [&#x24C9;][1]
+
+Creates an object composed of keys returned from running each element of the `collection` through the `callback`. The corresponding value of each key is an array of elements passed to `callback` that returned the key. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns the composed aggregate object.
+
+#### Example
+```js
+_.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+// => { '4': [4.2], '6': [6.1, 6.4] }
+
+_.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+// => { '4': [4.2], '6': [6.1, 6.4] }
+
+// using "_.pluck" callback shorthand
+_.groupBy(['one', 'two', 'three'], 'length');
+// => { '3': ['one', 'two'], '5': ['three'] }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_invokecollection-methodname--arg1-arg2-"></a>`_.invoke(collection, methodName [, arg1, arg2, ...])`
+<a href="#_invokecollection-methodname--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2561 "View in source") [&#x24C9;][1]
+
+Invokes the method named by `methodName` on each element in the `collection`, returning an array of the results of each invoked method. Additional arguments will be passed to each invoked method. If `methodName` is a function, it will be invoked for, and `this` bound to, each element in the `collection`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `methodName` *(Function|String)*: The name of the method to invoke or the function invoked per iteration.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to invoke the method with.
+
+#### Returns
+*(Array)*: Returns a new array of the results of each invoked method.
+
+#### Example
+```js
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+// => [[1, 5, 7], [1, 2, 3]]
+
+_.invoke([123, 456], String.prototype.split, '');
+// => [['1', '2', '3'], ['4', '5', '6']]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_mapcollection--callbackidentity-thisarg"></a>`_.map(collection [, callback=identity, thisArg])`
+<a href="#_mapcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2613 "View in source") [&#x24C9;][1]
+
+Creates an array of values by running each element in the `collection` through the `callback`. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*collect*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a new array of the results of each `callback` execution.
+
+#### Example
+```js
+_.map([1, 2, 3], function(num) { return num * 3; });
+// => [3, 6, 9]
+
+_.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+// => [3, 6, 9] (order is not guaranteed)
+
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+// using "_.pluck" callback shorthand
+_.map(stooges, 'name');
+// => ['moe', 'larry']
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_maxcollection--callbackidentity-thisarg"></a>`_.max(collection [, callback=identity, thisArg])`
+<a href="#_maxcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2670 "View in source") [&#x24C9;][1]
+
+Retrieves the maximum value of an `array`. If `callback` is passed, it will be executed for each value in the `array` to generate the criterion by which the value is ranked. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the maximum value.
+
+#### Example
+```js
+_.max([4, 2, 8, 6]);
+// => 8
+
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+_.max(stooges, function(stooge) { return stooge.age; });
+// => { 'name': 'larry', 'age': 50 };
+
+// using "_.pluck" callback shorthand
+_.max(stooges, 'age');
+// => { 'name': 'larry', 'age': 50 };
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_mincollection--callbackidentity-thisarg"></a>`_.min(collection [, callback=identity, thisArg])`
+<a href="#_mincollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2739 "View in source") [&#x24C9;][1]
+
+Retrieves the minimum value of an `array`. If `callback` is passed, it will be executed for each value in the `array` to generate the criterion by which the value is ranked. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the minimum value.
+
+#### Example
+```js
+_.min([4, 2, 8, 6]);
+// => 2
+
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+_.min(stooges, function(stooge) { return stooge.age; });
+// => { 'name': 'moe', 'age': 40 };
+
+// using "_.pluck" callback shorthand
+_.min(stooges, 'age');
+// => { 'name': 'moe', 'age': 40 };
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_pluckcollection-property"></a>`_.pluck(collection, property)`
+<a href="#_pluckcollection-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2789 "View in source") [&#x24C9;][1]
+
+Retrieves the value of a specified property from all elements in the `collection`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `property` *(String)*: The property to pluck.
+
+#### Returns
+*(Array)*: Returns a new array of property values.
+
+#### Example
+```js
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+_.pluck(stooges, 'name');
+// => ['moe', 'larry']
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_reducecollection--callbackidentity-accumulator-thisarg"></a>`_.reduce(collection [, callback=identity, accumulator, thisArg])`
+<a href="#_reducecollection--callbackidentity-accumulator-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2821 "View in source") [&#x24C9;][1]
+
+Reduces a `collection` to a value that is the accumulated result of running each element in the `collection` through the `callback`, where each successive `callback` execution consumes the return value of the previous execution. If `accumulator` is not passed, the first element of the `collection` will be used as the initial `accumulator` value. The `callback` is bound to `thisArg` and invoked with four arguments; *(accumulator, value, index|key, collection)*.
+
+#### Aliases
+*foldl, inject*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function)*: The function called per iteration.
+3. `[accumulator]` *(Mixed)*: Initial value of the accumulator.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the accumulated value.
+
+#### Example
+```js
+var sum = _.reduce([1, 2, 3], function(sum, num) {
+  return sum + num;
+});
+// => 6
+
+var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+  result[key] = num * 3;
+  return result;
+}, {});
+// => { 'a': 3, 'b': 6, 'c': 9 }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_reducerightcollection--callbackidentity-accumulator-thisarg"></a>`_.reduceRight(collection [, callback=identity, accumulator, thisArg])`
+<a href="#_reducerightcollection--callbackidentity-accumulator-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2864 "View in source") [&#x24C9;][1]
+
+This method is similar to `_.reduce`, except that it iterates over a `collection` from right to left.
+
+#### Aliases
+*foldr*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function)*: The function called per iteration.
+3. `[accumulator]` *(Mixed)*: Initial value of the accumulator.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the accumulated value.
+
+#### Example
+```js
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+// => [4, 5, 2, 3, 0, 1]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_rejectcollection--callbackidentity-thisarg"></a>`_.reject(collection [, callback=identity, thisArg])`
+<a href="#_rejectcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2924 "View in source") [&#x24C9;][1]
+
+The opposite of `_.filter`, this method returns the elements of a `collection` that `callback` does **not** return truthy for.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a new array of elements that did **not** pass the  callback check.
+
+#### Example
+```js
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+// => [1, 3, 5]
+
+var food = [
+  { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+  { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+];
+
+// using "_.pluck" callback shorthand
+_.reject(food, 'organic');
+// => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+
+// using "_.where" callback shorthand
+_.reject(food, { 'type': 'fruit' });
+// => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_shufflecollection"></a>`_.shuffle(collection)`
+<a href="#_shufflecollection">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2945 "View in source") [&#x24C9;][1]
+
+Creates an array of shuffled `array` values, using a version of the Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to shuffle.
+
+#### Returns
+*(Array)*: Returns a new shuffled collection.
+
+#### Example
+```js
+_.shuffle([1, 2, 3, 4, 5, 6]);
+// => [4, 1, 6, 3, 5, 2]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_sizecollection"></a>`_.size(collection)`
+<a href="#_sizecollection">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2978 "View in source") [&#x24C9;][1]
+
+Gets the size of the `collection` by returning `collection.length` for arrays and array-like objects or the number of own enumerable properties for objects.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to inspect.
+
+#### Returns
+*(Number)*: Returns `collection.length` or number of own enumerable properties.
+
+#### Example
+```js
+_.size([1, 2]);
+// => 2
+
+_.size({ 'one': 1, 'two': 2, 'three': 3 });
+// => 3
+
+_.size('curly');
+// => 5
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_somecollection--callbackidentity-thisarg"></a>`_.some(collection [, callback=identity, thisArg])`
+<a href="#_somecollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3025 "View in source") [&#x24C9;][1]
+
+Checks if the `callback` returns a truthy value for **any** element of a `collection`. The function returns as soon as it finds passing value, and does not iterate over the entire `collection`. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Aliases
+*any*
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Boolean)*: Returns `true` if any element passes the callback check,  else `false`.
+
+#### Example
+```js
+_.some([null, 0, 'yes', false], Boolean);
+// => true
+
+var food = [
+  { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+  { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+];
+
+// using "_.pluck" callback shorthand
+_.some(food, 'organic');
+// => true
+
+// using "_.where" callback shorthand
+_.some(food, { 'type': 'meat' });
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_sortbycollection--callbackidentity-thisarg"></a>`_.sortBy(collection [, callback=identity, thisArg])`
+<a href="#_sortbycollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3081 "View in source") [&#x24C9;][1]
+
+Creates an array of elements, sorted in ascending order by the results of running each element in the `collection` through the `callback`. This method performs a stable sort, that is, it will preserve the original sort order of equal elements. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, index|key, collection)*.
+
+If a property name is passed for `callback`, the created "_.pluck" style callback will return the property value of the given element.
+
+If an object is passed for `callback`, the created "_.where" style callback will return `true` for elements that have the propeties of the given object, else `false`.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `[callback=identity]` *(Function|Object|String)*: The function called per iteration. If a property name or object is passed, it will be used to create a "_.pluck" or "_.where" style callback, respectively.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a new array of sorted elements.
+
+#### Example
+```js
+_.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+// => [3, 1, 2]
+
+_.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+// => [3, 1, 2]
+
+// using "_.pluck" callback shorthand
+_.sortBy(['banana', 'strawberry', 'apple'], 'length');
+// => ['apple', 'banana', 'strawberry']
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_toarraycollection"></a>`_.toArray(collection)`
+<a href="#_toarraycollection">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3116 "View in source") [&#x24C9;][1]
+
+Converts the `collection` to an array.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to convert.
+
+#### Returns
+*(Array)*: Returns the new converted array.
+
+#### Example
+```js
+(function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+// => [2, 3, 4]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_wherecollection-properties"></a>`_.where(collection, properties)`
+<a href="#_wherecollection-properties">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3148 "View in source") [&#x24C9;][1]
+
+Examines each element in a `collection`, returning an array of all elements that have the given `properties`. When checking `properties`, this method performs a deep comparison between values to determine if they are equivalent to each other.
+
+#### Arguments
+1. `collection` *(Array|Object|String)*: The collection to iterate over.
+2. `properties` *(Object)*: The object of property values to filter by.
+
+#### Returns
+*(Array)*: Returns a new array of elements that have the given `properties`.
+
+#### Example
+```js
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+_.where(stooges, { 'age': 40 });
+// => [{ 'name': 'moe', 'age': 40 }]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `âFunctionsâ Methods`
+
+<!-- div -->
+
+### <a id="_aftern-func"></a>`_.after(n, func)`
+<a href="#_aftern-func">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4007 "View in source") [&#x24C9;][1]
+
+Creates a function that is restricted to executing `func` only after it is called `n` times. The `func` is executed with the `this` binding of the created function.
+
+#### Arguments
+1. `n` *(Number)*: The number of times the function must be called before it is executed.
+2. `func` *(Function)*: The function to restrict.
+
+#### Returns
+*(Function)*: Returns the new restricted function.
+
+#### Example
+```js
+var renderNotes = _.after(notes.length, render);
+_.forEach(notes, function(note) {
+  note.asyncSave({ 'success': renderNotes });
+});
+// `renderNotes` is run once, after all notes have saved
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_bindfunc--thisarg-arg1-arg2-"></a>`_.bind(func [, thisArg, arg1, arg2, ...])`
+<a href="#_bindfunc--thisarg-arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4040 "View in source") [&#x24C9;][1]
+
+Creates a function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends any additional `bind` arguments to those passed to the bound function.
+
+#### Arguments
+1. `func` *(Function)*: The function to bind.
+2. `[thisArg]` *(Mixed)*: The `this` binding of `func`.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to be partially applied.
+
+#### Returns
+*(Function)*: Returns the new bound function.
+
+#### Example
+```js
+var func = function(greeting) {
+  return greeting + ' ' + this.name;
+};
+
+func = _.bind(func, { 'name': 'moe' }, 'hi');
+func();
+// => 'hi moe'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_bindallobject--methodname1-methodname2-"></a>`_.bindAll(object [, methodName1, methodName2, ...])`
+<a href="#_bindallobject--methodname1-methodname2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4071 "View in source") [&#x24C9;][1]
+
+Binds methods on `object` to `object`, overwriting the existing method. Method names may be specified as individual arguments or as arrays of method names. If no method names are provided, all the function properties of `object` will be bound.
+
+#### Arguments
+1. `object` *(Object)*: The object to bind and assign the bound methods to.
+2. `[methodName1, methodName2, ...]` *(String)*: Method names on the object to bind.
+
+#### Returns
+*(Object)*: Returns `object`.
+
+#### Example
+```js
+var view = {
+ 'label': 'docs',
+ 'onClick': function() { alert('clicked ' + this.label); }
+};
+
+_.bindAll(view);
+jQuery('#docs').on('click', view.onClick);
+// => alerts 'clicked docs', when the button is clicked
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_bindkeyobject-key--arg1-arg2-"></a>`_.bindKey(object, key [, arg1, arg2, ...])`
+<a href="#_bindkeyobject-key--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4117 "View in source") [&#x24C9;][1]
+
+Creates a function that, when called, invokes the method at `object[key]` and prepends any additional `bindKey` arguments to those passed to the bound function. This method differs from `_.bind` by allowing bound functions to reference methods that will be redefined or don't yet exist. See http://michaux.ca/articles/lazy-function-definition-pattern.
+
+#### Arguments
+1. `object` *(Object)*: The object the method belongs to.
+2. `key` *(String)*: The key of the method.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to be partially applied.
+
+#### Returns
+*(Function)*: Returns the new bound function.
+
+#### Example
+```js
+var object = {
+  'name': 'moe',
+  'greet': function(greeting) {
+    return greeting + ' ' + this.name;
+  }
+};
+
+var func = _.bindKey(object, 'greet', 'hi');
+func();
+// => 'hi moe'
+
+object.greet = function(greeting) {
+  return greeting + ', ' + this.name + '!';
+};
+
+func();
+// => 'hi, moe!'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_composefunc1-func2-"></a>`_.compose([func1, func2, ...])`
+<a href="#_composefunc1-func2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4140 "View in source") [&#x24C9;][1]
+
+Creates a function that is the composition of the passed functions, where each function consumes the return value of the function that follows. For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. Each function is executed with the `this` binding of the composed function.
+
+#### Arguments
+1. `[func1, func2, ...]` *(Function)*: Functions to compose.
+
+#### Returns
+*(Function)*: Returns the new composed function.
+
+#### Example
+```js
+var greet = function(name) { return 'hi ' + name; };
+var exclaim = function(statement) { return statement + '!'; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+// => 'hi moe!'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_debouncefunc-wait-immediate"></a>`_.debounce(func, wait, immediate)`
+<a href="#_debouncefunc-wait-immediate">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4173 "View in source") [&#x24C9;][1]
+
+Creates a function that will delay the execution of `func` until after `wait` milliseconds have elapsed since the last time it was invoked. Pass `true` for `immediate` to cause debounce to invoke `func` on the leading, instead of the trailing, edge of the `wait` timeout. Subsequent calls to the debounced function will return the result of the last `func` call.
+
+#### Arguments
+1. `func` *(Function)*: The function to debounce.
+2. `wait` *(Number)*: The number of milliseconds to delay.
+3. `immediate` *(Boolean)*: A flag to indicate execution is on the leading edge of the timeout.
+
+#### Returns
+*(Function)*: Returns the new debounced function.
+
+#### Example
+```js
+var lazyLayout = _.debounce(calculateLayout, 300);
+jQuery(window).on('resize', lazyLayout);
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_deferfunc--arg1-arg2-"></a>`_.defer(func [, arg1, arg2, ...])`
+<a href="#_deferfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4237 "View in source") [&#x24C9;][1]
+
+Defers executing the `func` function until the current call stack has cleared. Additional arguments will be passed to `func` when it is invoked.
+
+#### Arguments
+1. `func` *(Function)*: The function to defer.
+2. `[arg1, arg2, ...]` *(Mixed)*: Arguments to invoke the function with.
+
+#### Returns
+*(Number)*: Returns the `setTimeout` timeout id.
+
+#### Example
+```js
+_.defer(function() { alert('deferred'); });
+// returns from the function before `alert` is called
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_delayfunc-wait--arg1-arg2-"></a>`_.delay(func, wait [, arg1, arg2, ...])`
+<a href="#_delayfunc-wait--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4217 "View in source") [&#x24C9;][1]
+
+Executes the `func` function after `wait` milliseconds. Additional arguments will be passed to `func` when it is invoked.
+
+#### Arguments
+1. `func` *(Function)*: The function to delay.
+2. `wait` *(Number)*: The number of milliseconds to delay execution.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to invoke the function with.
+
+#### Returns
+*(Number)*: Returns the `setTimeout` timeout id.
+
+#### Example
+```js
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+// => 'logged later' (Appears after one second.)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_memoizefunc--resolver"></a>`_.memoize(func [, resolver])`
+<a href="#_memoizefunc--resolver">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4265 "View in source") [&#x24C9;][1]
+
+Creates a function that memoizes the result of `func`. If `resolver` is passed, it will be used to determine the cache key for storing the result based on the arguments passed to the memoized function. By default, the first argument passed to the memoized function is used as the cache key. The `func` is executed with the `this` binding of the memoized function.
+
+#### Arguments
+1. `func` *(Function)*: The function to have its output memoized.
+2. `[resolver]` *(Function)*: A function used to resolve the cache key.
+
+#### Returns
+*(Function)*: Returns the new memoizing function.
+
+#### Example
+```js
+var fibonacci = _.memoize(function(n) {
+  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_oncefunc"></a>`_.once(func)`
+<a href="#_oncefunc">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4292 "View in source") [&#x24C9;][1]
+
+Creates a function that is restricted to execute `func` once. Repeat calls to the function will return the value of the first call. The `func` is executed with the `this` binding of the created function.
+
+#### Arguments
+1. `func` *(Function)*: The function to restrict.
+
+#### Returns
+*(Function)*: Returns the new restricted function.
+
+#### Example
+```js
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// `initialize` executes `createApplication` once
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_partialfunc--arg1-arg2-"></a>`_.partial(func [, arg1, arg2, ...])`
+<a href="#_partialfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4327 "View in source") [&#x24C9;][1]
+
+Creates a function that, when called, invokes `func` with any additional `partial` arguments prepended to those passed to the new function. This method is similar to `_.bind`, except it does **not** alter the `this` binding.
+
+#### Arguments
+1. `func` *(Function)*: The function to partially apply arguments to.
+2. `[arg1, arg2, ...]` *(Mixed)*: Arguments to be partially applied.
+
+#### Returns
+*(Function)*: Returns the new partially applied function.
+
+#### Example
+```js
+var greet = function(greeting, name) { return greeting + ' ' + name; };
+var hi = _.partial(greet, 'hi');
+hi('moe');
+// => 'hi moe'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_partialrightfunc--arg1-arg2-"></a>`_.partialRight(func [, arg1, arg2, ...])`
+<a href="#_partialrightfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4358 "View in source") [&#x24C9;][1]
+
+This method is similar to `_.partial`, except that `partial` arguments are appended to those passed to the new function.
+
+#### Arguments
+1. `func` *(Function)*: The function to partially apply arguments to.
+2. `[arg1, arg2, ...]` *(Mixed)*: Arguments to be partially applied.
+
+#### Returns
+*(Function)*: Returns the new partially applied function.
+
+#### Example
+```js
+var defaultsDeep = _.partialRight(_.merge, _.defaults);
+
+var options = {
+  'variable': 'data',
+  'imports': { 'jq': $ }
+};
+
+defaultsDeep(options, _.templateSettings);
+
+options.variable
+// => 'data'
+
+options.imports
+// => { '_': _, 'jq': $ }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_throttlefunc-wait"></a>`_.throttle(func, wait)`
+<a href="#_throttlefunc-wait">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4380 "View in source") [&#x24C9;][1]
+
+Creates a function that, when executed, will only call the `func` function at most once per every `wait` milliseconds. If the throttled function is invoked more than once during the `wait` timeout, `func` will also be called on the trailing edge of the timeout. Subsequent calls to the throttled function will return the result of the last `func` call.
+
+#### Arguments
+1. `func` *(Function)*: The function to throttle.
+2. `wait` *(Number)*: The number of milliseconds to throttle executions to.
+
+#### Returns
+*(Function)*: Returns the new throttled function.
+
+#### Example
+```js
+var throttled = _.throttle(updatePosition, 100);
+jQuery(window).on('scroll', throttled);
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_wrapvalue-wrapper"></a>`_.wrap(value, wrapper)`
+<a href="#_wrapvalue-wrapper">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4433 "View in source") [&#x24C9;][1]
+
+Creates a function that passes `value` to the `wrapper` function as its first argument. Additional arguments passed to the function are appended to those passed to the `wrapper` function. The `wrapper` is executed with the `this` binding of the created function.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to wrap.
+2. `wrapper` *(Function)*: The wrapper function.
+
+#### Returns
+*(Function)*: Returns the new function.
+
+#### Example
+```js
+var hello = function(name) { return 'hello ' + name; };
+hello = _.wrap(hello, function(func) {
+  return 'before, ' + func('moe') + ', after';
+});
+hello();
+// => 'before, hello moe, after'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `âObjectsâ Methods`
+
+<!-- div -->
+
+### <a id="_assignobject--source1-source2--callback-thisarg"></a>`_.assign(object [, source1, source2, ..., callback, thisArg])`
+<a href="#_assignobject--source1-source2--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1062 "View in source") [&#x24C9;][1]
+
+Assigns own enumerable properties of source object(s) to the destination object. Subsequent sources will overwrite propery assignments of previous sources. If a `callback` function is passed, it will be executed to produce the assigned values. The `callback` is bound to `thisArg` and invoked with two arguments; *(objectValue, sourceValue)*.
+
+#### Aliases
+*extend*
+
+#### Arguments
+1. `object` *(Object)*: The destination object.
+2. `[source1, source2, ...]` *(Object)*: The source objects.
+3. `[callback]` *(Function)*: The function to customize assigning values.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns the destination object.
+
+#### Example
+```js
+_.assign({ 'name': 'moe' }, { 'age': 40 });
+// => { 'name': 'moe', 'age': 40 }
+
+var defaults = _.partialRight(_.assign, function(a, b) {
+  return typeof a == 'undefined' ? b : a;
+});
+
+var food = { 'name': 'apple' };
+defaults(food, { 'name': 'banana', 'type': 'fruit' });
+// => { 'name': 'apple', 'type': 'fruit' }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_clonevalue--deepfalse-callback-thisarg"></a>`_.clone(value [, deep=false, callback, thisArg])`
+<a href="#_clonevalue--deepfalse-callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1117 "View in source") [&#x24C9;][1]
+
+Creates a clone of `value`. If `deep` is `true`, nested objects will also be cloned, otherwise they will be assigned by reference. If a `callback` function is passed, it will be executed to produce the cloned values. If `callback` returns `undefined`, cloning will be handled by the method instead. The `callback` is bound to `thisArg` and invoked with one argument; *(value)*.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to clone.
+2. `[deep=false]` *(Boolean)*: A flag to indicate a deep clone.
+3. `[callback]` *(Function)*: The function to customize cloning values.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the cloned `value`.
+
+#### Example
+```js
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+var shallow = _.clone(stooges);
+shallow[0] === stooges[0];
+// => true
+
+var deep = _.clone(stooges, true);
+deep[0] === stooges[0];
+// => false
+
+_.mixin({
+  'clone': _.partialRight(_.clone, function(value) {
+    return _.isElement(value) ? value.cloneNode(false) : undefined;
+  })
+});
+
+var clone = _.clone(document.body);
+clone.childNodes.length;
+// => 0
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_clonedeepvalue--callback-thisarg"></a>`_.cloneDeep(value [, callback, thisArg])`
+<a href="#_clonedeepvalue--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1242 "View in source") [&#x24C9;][1]
+
+Creates a deep clone of `value`. If a `callback` function is passed, it will be executed to produce the cloned values. If `callback` returns the value it was passed, cloning will be handled by the method instead. The `callback` is bound to `thisArg` and invoked with one argument; *(value)*.
+
+Note: This function is loosely based on the structured clone algorithm. Functions and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and objects created by constructors other than `Object` are cloned to plain `Object` objects. See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to deep clone.
+2. `[callback]` *(Function)*: The function to customize cloning values.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Mixed)*: Returns the deep cloned `value`.
+
+#### Example
+```js
+var stooges = [
+  { 'name': 'moe', 'age': 40 },
+  { 'name': 'larry', 'age': 50 }
+];
+
+var deep = _.cloneDeep(stooges);
+deep[0] === stooges[0];
+// => false
+
+var view = {
+  'label': 'docs',
+  'node': element
+};
+
+var clone = _.cloneDeep(view, function(value) {
+  return _.isElement(value) ? value.cloneNode(true) : value;
+});
+
+clone.node == view.node;
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_defaultsobject--source1-source2-"></a>`_.defaults(object [, source1, source2, ...])`
+<a href="#_defaultsobject--source1-source2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1266 "View in source") [&#x24C9;][1]
+
+Assigns own enumerable properties of source object(s) to the destination object for all destination properties that resolve to `undefined`. Once a property is set, additional defaults of the same property will be ignored.
+
+#### Arguments
+1. `object` *(Object)*: The destination object.
+2. `[source1, source2, ...]` *(Object)*: The source objects.
+
+#### Returns
+*(Object)*: Returns the destination object.
+
+#### Example
+```js
+var food = { 'name': 'apple' };
+_.defaults(food, { 'name': 'banana', 'type': 'fruit' });
+// => { 'name': 'apple', 'type': 'fruit' }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_forinobject--callbackidentity-thisarg"></a>`_.forIn(object [, callback=identity, thisArg])`
+<a href="#_forinobject--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L882 "View in source") [&#x24C9;][1]
+
+Iterates over `object`'s own and inherited enumerable properties, executing the `callback` for each property. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`.
+
+#### Arguments
+1. `object` *(Object)*: The object to iterate over.
+2. `[callback=identity]` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns `object`.
+
+#### Example
+```js
+function Dog(name) {
+  this.name = name;
+}
+
+Dog.prototype.bark = function() {
+  alert('Woof, woof!');
+};
+
+_.forIn(new Dog('Dagny'), function(value, key) {
+  alert(key);
+});
+// => alerts 'name' and 'bark' (order is not guaranteed)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_forownobject--callbackidentity-thisarg"></a>`_.forOwn(object [, callback=identity, thisArg])`
+<a href="#_forownobject--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L907 "View in source") [&#x24C9;][1]
+
+Iterates over an object's own enumerable properties, executing the `callback` for each property. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`.
+
+#### Arguments
+1. `object` *(Object)*: The object to iterate over.
+2. `[callback=identity]` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns `object`.
+
+#### Example
+```js
+_.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+  alert(key);
+});
+// => alerts '0', '1', and 'length' (order is not guaranteed)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_functionsobject"></a>`_.functions(object)`
+<a href="#_functionsobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1283 "View in source") [&#x24C9;][1]
+
+Creates a sorted array of all enumerable properties, own and inherited, of `object` that have function values.
+
+#### Aliases
+*methods*
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns a new array of property names that have function values.
+
+#### Example
+```js
+_.functions(_);
+// => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_hasobject-property"></a>`_.has(object, property)`
+<a href="#_hasobject-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1308 "View in source") [&#x24C9;][1]
+
+Checks if the specified object `property` exists and is a direct property, instead of an inherited property.
+
+#### Arguments
+1. `object` *(Object)*: The object to check.
+2. `property` *(String)*: The property to check for.
+
+#### Returns
+*(Boolean)*: Returns `true` if key is a direct property, else `false`.
+
+#### Example
+```js
+_.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_invertobject"></a>`_.invert(object)`
+<a href="#_invertobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1325 "View in source") [&#x24C9;][1]
+
+Creates an object composed of the inverted keys and values of the given `object`.
+
+#### Arguments
+1. `object` *(Object)*: The object to invert.
+
+#### Returns
+*(Object)*: Returns the created inverted object.
+
+#### Example
+```js
+_.invert({ 'first': 'moe', 'second': 'larry' });
+// => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isargumentsvalue"></a>`_.isArguments(value)`
+<a href="#_isargumentsvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L843 "View in source") [&#x24C9;][1]
+
+Checks if `value` is an `arguments` object.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is an `arguments` object, else `false`.
+
+#### Example
+```js
+(function() { return _.isArguments(arguments); })(1, 2, 3);
+// => true
+
+_.isArguments([1, 2, 3]);
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isarrayvalue"></a>`_.isArray(value)`
+<a href="#_isarrayvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L925 "View in source") [&#x24C9;][1]
+
+Checks if `value` is an array.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is an array, else `false`.
+
+#### Example
+```js
+(function() { return _.isArray(arguments); })();
+// => false
+
+_.isArray([1, 2, 3]);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isbooleanvalue"></a>`_.isBoolean(value)`
+<a href="#_isbooleanvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1351 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a boolean value.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a boolean value, else `false`.
+
+#### Example
+```js
+_.isBoolean(null);
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isdatevalue"></a>`_.isDate(value)`
+<a href="#_isdatevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1368 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a date.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a date, else `false`.
+
+#### Example
+```js
+_.isDate(new Date);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_iselementvalue"></a>`_.isElement(value)`
+<a href="#_iselementvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1385 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a DOM element.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a DOM element, else `false`.
+
+#### Example
+```js
+_.isElement(document.body);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isemptyvalue"></a>`_.isEmpty(value)`
+<a href="#_isemptyvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1410 "View in source") [&#x24C9;][1]
+
+Checks if `value` is empty. Arrays, strings, or `arguments` objects with a length of `0` and objects with no own enumerable properties are considered "empty".
+
+#### Arguments
+1. `value` *(Array|Object|String)*: The value to inspect.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is empty, else `false`.
+
+#### Example
+```js
+_.isEmpty([1, 2, 3]);
+// => false
+
+_.isEmpty({});
+// => true
+
+_.isEmpty('');
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isequala-b--callback-thisarg"></a>`_.isEqual(a, b [, callback, thisArg])`
+<a href="#_isequala-b--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1469 "View in source") [&#x24C9;][1]
+
+Performs a deep comparison between two values to determine if they are equivalent to each other. If `callback` is passed, it will be executed to compare values. If `callback` returns `undefined`, comparisons will be handled by the method instead. The `callback` is bound to `thisArg` and invoked with two arguments; *(a, b)*.
+
+#### Arguments
+1. `a` *(Mixed)*: The value to compare.
+2. `b` *(Mixed)*: The other value to compare.
+3. `[callback]` *(Function)*: The function to customize comparing values.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the values are equvalent, else `false`.
+
+#### Example
+```js
+var moe = { 'name': 'moe', 'age': 40 };
+var copy = { 'name': 'moe', 'age': 40 };
+
+moe == copy;
+// => false
+
+_.isEqual(moe, copy);
+// => true
+
+var words = ['hello', 'goodbye'];
+var otherWords = ['hi', 'goodbye'];
+
+_.isEqual(words, otherWords, function(a, b) {
+  var reGreet = /^(?:hello|hi)$/i,
+      aGreet = _.isString(a) && reGreet.test(a),
+      bGreet = _.isString(b) && reGreet.test(b);
+
+  return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+});
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isfinitevalue"></a>`_.isFinite(value)`
+<a href="#_isfinitevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1650 "View in source") [&#x24C9;][1]
+
+Checks if `value` is, or can be coerced to, a finite number.
+
+Note: This is not the same as native `isFinite`, which will return true for booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is finite, else `false`.
+
+#### Example
+```js
+_.isFinite(-101);
+// => true
+
+_.isFinite('10');
+// => true
+
+_.isFinite(true);
+// => false
+
+_.isFinite('');
+// => false
+
+_.isFinite(Infinity);
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isfunctionvalue"></a>`_.isFunction(value)`
+<a href="#_isfunctionvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1667 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a function.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a function, else `false`.
+
+#### Example
+```js
+_.isFunction(_);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isnanvalue"></a>`_.isNaN(value)`
+<a href="#_isnanvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1730 "View in source") [&#x24C9;][1]
+
+Checks if `value` is `NaN`.
+
+Note: This is not the same as native `isNaN`, which will return `true` for `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is `NaN`, else `false`.
+
+#### Example
+```js
+_.isNaN(NaN);
+// => true
+
+_.isNaN(new Number(NaN));
+// => true
+
+isNaN(undefined);
+// => true
+
+_.isNaN(undefined);
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isnullvalue"></a>`_.isNull(value)`
+<a href="#_isnullvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1752 "View in source") [&#x24C9;][1]
+
+Checks if `value` is `null`.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is `null`, else `false`.
+
+#### Example
+```js
+_.isNull(null);
+// => true
+
+_.isNull(undefined);
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isnumbervalue"></a>`_.isNumber(value)`
+<a href="#_isnumbervalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1769 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a number.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a number, else `false`.
+
+#### Example
+```js
+_.isNumber(8.4 * 5);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isobjectvalue"></a>`_.isObject(value)`
+<a href="#_isobjectvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1697 "View in source") [&#x24C9;][1]
+
+Checks if `value` is the language type of Object. *(e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)*
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is an object, else `false`.
+
+#### Example
+```js
+_.isObject({});
+// => true
+
+_.isObject([1, 2, 3]);
+// => true
+
+_.isObject(1);
+// => false
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isplainobjectvalue"></a>`_.isPlainObject(value)`
+<a href="#_isplainobjectvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1797 "View in source") [&#x24C9;][1]
+
+Checks if a given `value` is an object created by the `Object` constructor.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if `value` is a plain object, else `false`.
+
+#### Example
+```js
+function Stooge(name, age) {
+  this.name = name;
+  this.age = age;
+}
+
+_.isPlainObject(new Stooge('moe', 40));
+// => false
+
+_.isPlainObject([1, 2, 3]);
+// => false
+
+_.isPlainObject({ 'name': 'moe', 'age': 40 });
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isregexpvalue"></a>`_.isRegExp(value)`
+<a href="#_isregexpvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1822 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a regular expression.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a regular expression, else `false`.
+
+#### Example
+```js
+_.isRegExp(/moe/);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isstringvalue"></a>`_.isString(value)`
+<a href="#_isstringvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1839 "View in source") [&#x24C9;][1]
+
+Checks if `value` is a string.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is a string, else `false`.
+
+#### Example
+```js
+_.isString('moe');
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_isundefinedvalue"></a>`_.isUndefined(value)`
+<a href="#_isundefinedvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1856 "View in source") [&#x24C9;][1]
+
+Checks if `value` is `undefined`.
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true`, if the `value` is `undefined`, else `false`.
+
+#### Example
+```js
+_.isUndefined(void 0);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_keysobject"></a>`_.keys(object)`
+<a href="#_keysobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L944 "View in source") [&#x24C9;][1]
+
+Creates an array composed of the own enumerable property names of `object`.
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns a new array of property names.
+
+#### Example
+```js
+_.keys({ 'one': 1, 'two': 2, 'three': 3 });
+// => ['one', 'two', 'three'] (order is not guaranteed)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_mergeobject--source1-source2--callback-thisarg"></a>`_.merge(object [, source1, source2, ..., callback, thisArg])`
+<a href="#_mergeobject--source1-source2--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1916 "View in source") [&#x24C9;][1]
+
+Recursively merges own enumerable properties of the source object(s), that don't resolve to `undefined`, into the destination object. Subsequent sources will overwrite propery assignments of previous sources. If a `callback` function is passed, it will be executed to produce the merged values of the destination and source properties. If `callback` returns `undefined`, merging will be handled by the method instead. The `callback` is bound to `thisArg` and invoked with two arguments; *(objectValue, sourceValue)*.
+
+#### Arguments
+1. `object` *(Object)*: The destination object.
+2. `[source1, source2, ...]` *(Object)*: The source objects.
+3. `[callback]` *(Function)*: The function to customize merging properties.
+4. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns the destination object.
+
+#### Example
+```js
+var names = {
+  'stooges': [
+    { 'name': 'moe' },
+    { 'name': 'larry' }
+  ]
+};
+
+var ages = {
+  'stooges': [
+    { 'age': 40 },
+    { 'age': 50 }
+  ]
+};
+
+_.merge(names, ages);
+// => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
+
+var food = {
+  'fruits': ['apple'],
+  'vegetables': ['beet']
+};
+
+var otherFood = {
+  'fruits': ['banana'],
+  'vegetables': ['carrot']
+};
+
+_.merge(food, otherFood, function(a, b) {
+  return _.isArray(a) ? a.concat(b) : undefined;
+});
+// => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_omitobject-callback-prop1-prop2--thisarg"></a>`_.omit(object, callback|[prop1, prop2, ..., thisArg])`
+<a href="#_omitobject-callback-prop1-prop2--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2023 "View in source") [&#x24C9;][1]
+
+Creates a shallow clone of `object` excluding the specified properties. Property names may be specified as individual arguments or as arrays of property names. If a `callback` function is passed, it will be executed for each property in the `object`, omitting the properties `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, key, object)*.
+
+#### Arguments
+1. `object` *(Object)*: The source object.
+2. `callback|[prop1, prop2, ...]` *(Function|String)*: The properties to omit or the function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns an object without the omitted properties.
+
+#### Example
+```js
+_.omit({ 'name': 'moe', 'age': 40 }, 'age');
+// => { 'name': 'moe' }
+
+_.omit({ 'name': 'moe', 'age': 40 }, function(value) {
+  return typeof value == 'number';
+});
+// => { 'name': 'moe' }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_pairsobject"></a>`_.pairs(object)`
+<a href="#_pairsobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2057 "View in source") [&#x24C9;][1]
+
+Creates a two dimensional array of the given object's key-value pairs, i.e. `[[key1, value1], [key2, value2]]`.
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns new array of key-value pairs.
+
+#### Example
+```js
+_.pairs({ 'moe': 30, 'larry': 40 });
+// => [['moe', 30], ['larry', 40]] (order is not guaranteed)
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_pickobject-callback-prop1-prop2--thisarg"></a>`_.pick(object, callback|[prop1, prop2, ..., thisArg])`
+<a href="#_pickobject-callback-prop1-prop2--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2095 "View in source") [&#x24C9;][1]
+
+Creates a shallow clone of `object` composed of the specified properties. Property names may be specified as individual arguments or as arrays of property names. If `callback` is passed, it will be executed for each property in the `object`, picking the properties `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with three arguments; *(value, key, object)*.
+
+#### Arguments
+1. `object` *(Object)*: The source object.
+2. `callback|[prop1, prop2, ...]` *(Array|Function|String)*: The function called per iteration or properties to pick, either as individual arguments or arrays.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Object)*: Returns an object composed of the picked properties.
+
+#### Example
+```js
+_.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
+// => { 'name': 'moe' }
+
+_.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
+  return key.charAt(0) != '_';
+});
+// => { 'name': 'moe' }
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_valuesobject"></a>`_.values(object)`
+<a href="#_valuesobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2132 "View in source") [&#x24C9;][1]
+
+Creates an array composed of the own enumerable property values of `object`.
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns a new array of property values.
+
+#### Example
+```js
+_.values({ 'one': 1, 'two': 2, 'three': 3 });
+// => [1, 2, 3]
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `âUtilitiesâ Methods`
+
+<!-- div -->
+
+### <a id="_escapestring"></a>`_.escape(string)`
+<a href="#_escapestring">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4457 "View in source") [&#x24C9;][1]
+
+Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding HTML entities.
+
+#### Arguments
+1. `string` *(String)*: The string to escape.
+
+#### Returns
+*(String)*: Returns the escaped string.
+
+#### Example
+```js
+_.escape('Moe, Larry & Curly');
+// => 'Moe, Larry &amp; Curly'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_identityvalue"></a>`_.identity(value)`
+<a href="#_identityvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4475 "View in source") [&#x24C9;][1]
+
+This function returns the first argument passed to it.
+
+#### Arguments
+1. `value` *(Mixed)*: Any value.
+
+#### Returns
+*(Mixed)*: Returns `value`.
+
+#### Example
+```js
+var moe = { 'name': 'moe' };
+moe === _.identity(moe);
+// => true
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_mixinobject"></a>`_.mixin(object)`
+<a href="#_mixinobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4501 "View in source") [&#x24C9;][1]
+
+Adds functions properties of `object` to the `lodash` function and chainable wrapper.
+
+#### Arguments
+1. `object` *(Object)*: The object of function properties to add to `lodash`.
+
+#### Example
+```js
+_.mixin({
+  'capitalize': function(string) {
+    return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+  }
+});
+
+_.capitalize('moe');
+// => 'Moe'
+
+_('moe').capitalize();
+// => 'Moe'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_noconflict"></a>`_.noConflict()`
+<a href="#_noconflict">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4525 "View in source") [&#x24C9;][1]
+
+Reverts the '_' variable to its previous value and returns a reference to the `lodash` function.
+
+#### Returns
+*(Function)*: Returns the `lodash` function.
+
+#### Example
+```js
+var lodash = _.noConflict();
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_randommin0-max1"></a>`_.random([min=0, max=1])`
+<a href="#_randommin0-max1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4548 "View in source") [&#x24C9;][1]
+
+Produces a random number between `min` and `max` *(inclusive)*. If only one argument is passed, a number between `0` and the given number will be returned.
+
+#### Arguments
+1. `[min=0]` *(Number)*: The minimum possible value.
+2. `[max=1]` *(Number)*: The maximum possible value.
+
+#### Returns
+*(Number)*: Returns a random number.
+
+#### Example
+```js
+_.random(0, 5);
+// => a number between 0 and 5
+
+_.random(5);
+// => also a number between 0 and 5
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_resultobject-property"></a>`_.result(object, property)`
+<a href="#_resultobject-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4586 "View in source") [&#x24C9;][1]
+
+Resolves the value of `property` on `object`. If `property` is a function, it will be invoked and its result returned, else the property value is returned. If `object` is falsey, then `null` is returned.
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+2. `property` *(String)*: The property to get the value of.
+
+#### Returns
+*(Mixed)*: Returns the resolved value.
+
+#### Example
+```js
+var object = {
+  'cheese': 'crumpets',
+  'stuff': function() {
+    return 'nonsense';
+  }
+};
+
+_.result(object, 'cheese');
+// => 'crumpets'
+
+_.result(object, 'stuff');
+// => 'nonsense'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatetext-data-options"></a>`_.template(text, data, options)`
+<a href="#_templatetext-data-options">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4674 "View in source") [&#x24C9;][1]
+
+A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code.
+
+Note: In the development build, `_.template` utilizes sourceURLs for easier debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+
+Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp` build and using precompiled templates, or loading Lo-Dash in a sandbox.
+
+For more information on precompiling templates see:<br>
+http://lodash.com/#custom-builds
+
+For more information on Chrome extension sandboxes see:<br>
+http://developer.chrome.com/stable/extensions/sandboxingEval.html
+
+#### Arguments
+1. `text` *(String)*: The template text.
+2. `data` *(Obect)*: The data object used to populate the text.
+3. `options` *(Object)*: The options object. escape - The "escape" delimiter regexp. evaluate - The "evaluate" delimiter regexp. interpolate - The "interpolate" delimiter regexp. sourceURL - The sourceURL of the template's compiled source. variable - The data object variable name.
+
+#### Returns
+*(Function, String)*: Returns a compiled function when no `data` object  is given, else it returns the interpolated text.
+
+#### Example
+```js
+// using a compiled template
+var compiled = _.template('hello <%= name %>');
+compiled({ 'name': 'moe' });
+// => 'hello moe'
+
+var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
+_.template(list, { 'people': ['moe', 'larry'] });
+// => '<li>moe</li><li>larry</li>'
+
+// using the "escape" delimiter to escape HTML in data property values
+_.template('<b><%- value %></b>', { 'value': '<script>' });
+// => '<b>&lt;script&gt;</b>'
+
+// using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+_.template('hello ${ name }', { 'name': 'curly' });
+// => 'hello curly'
+
+// using the internal `print` function in "evaluate" delimiters
+_.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
+// => 'hello stooge!'
+
+// using custom template delimiters
+_.templateSettings = {
+  'interpolate': /{{([\s\S]+?)}}/g
+};
+
+_.template('hello {{ name }}!', { 'name': 'mustache' });
+// => 'hello mustache!'
+
+// using the `sourceURL` option to specify a custom sourceURL for the template
+var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+compiled(data);
+// => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+
+// using the `variable` option to ensure a with-statement isn't used in the compiled template
+var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+compiled.source;
+// => function(data) {
+  var __t, __p = '', __e = _.escape;
+  __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+  return __p;
+}
+
+// using the `source` property to inline compiled templates for meaningful
+// line numbers in error messages and a stack trace
+fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+  var JST = {\
+    "main": ' + _.template(mainText).source + '\
+  };\
+');
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_timesn-callback--thisarg"></a>`_.times(n, callback [, thisArg])`
+<a href="#_timesn-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4800 "View in source") [&#x24C9;][1]
+
+Executes the `callback` function `n` times, returning an array of the results of each `callback` execution. The `callback` is bound to `thisArg` and invoked with one argument; *(index)*.
+
+#### Arguments
+1. `n` *(Number)*: The number of times to execute the callback.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding of `callback`.
+
+#### Returns
+*(Array)*: Returns a new array of the results of each `callback` execution.
+
+#### Example
+```js
+var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+// => [3, 6, 4]
+
+_.times(3, function(n) { mage.castSpell(n); });
+// => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+
+_.times(3, function(n) { this.cast(n); }, mage);
+// => also calls `mage.castSpell(n)` three times
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_unescapestring"></a>`_.unescape(string)`
+<a href="#_unescapestring">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4826 "View in source") [&#x24C9;][1]
+
+The opposite of `_.escape`, this method converts the HTML entities `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their corresponding characters.
+
+#### Arguments
+1. `string` *(String)*: The string to unescape.
+
+#### Returns
+*(String)*: Returns the unescaped string.
+
+#### Example
+```js
+_.unescape('Moe, Larry &amp; Curly');
+// => 'Moe, Larry & Curly'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_uniqueidprefix"></a>`_.uniqueId([prefix])`
+<a href="#_uniqueidprefix">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4846 "View in source") [&#x24C9;][1]
+
+Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
+
+#### Arguments
+1. `[prefix]` *(String)*: The value to prefix the ID with.
+
+#### Returns
+*(String)*: Returns the unique ID.
+
+#### Example
+```js
+_.uniqueId('contact_');
+// => 'contact_104'
+
+_.uniqueId();
+// => '105'
+```
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Methods`
+
+<!-- div -->
+
+### <a id="_templatesettingsimports_"></a>`_.templateSettings.imports._`
+<a href="#_templatesettingsimports_">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L341 "View in source") [&#x24C9;][1]
+
+A reference to the `lodash` function.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- div -->
+
+## `Properties`
+
+<!-- div -->
+
+### <a id="_version"></a>`_.VERSION`
+<a href="#_version">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L5076 "View in source") [&#x24C9;][1]
+
+*(String)*: The semantic version number.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatesettings"></a>`_.templateSettings`
+<a href="#_templatesettings">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L293 "View in source") [&#x24C9;][1]
+
+*(Object)*: By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby *(ERB)*. Change the following template settings to use alternative delimiters.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatesettingsescape"></a>`_.templateSettings.escape`
+<a href="#_templatesettingsescape">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L301 "View in source") [&#x24C9;][1]
+
+*(RegExp)*: Used to detect `data` property values to be HTML-escaped.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatesettingsevaluate"></a>`_.templateSettings.evaluate`
+<a href="#_templatesettingsevaluate">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L309 "View in source") [&#x24C9;][1]
+
+*(RegExp)*: Used to detect code to be evaluated.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatesettingsinterpolate"></a>`_.templateSettings.interpolate`
+<a href="#_templatesettingsinterpolate">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L317 "View in source") [&#x24C9;][1]
+
+*(RegExp)*: Used to detect `data` property values to inject.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatesettingsvariable"></a>`_.templateSettings.variable`
+<a href="#_templatesettingsvariable">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L325 "View in source") [&#x24C9;][1]
+
+*(String)*: Used to reference the data object in the template text.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- div -->
+
+### <a id="_templatesettingsimports"></a>`_.templateSettings.imports`
+<a href="#_templatesettingsimports">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L333 "View in source") [&#x24C9;][1]
+
+*(Object)*: Used to import variables into the compiled template.
+
+* * *
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+<!-- /div -->
+
+
+  [1]: #Arrays "Jump back to the TOC."
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/index.js	(revision 533)
@@ -0,0 +1,1 @@
+module.exports = require('./lodash');
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/lodash.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/lodash.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/lodash.js	(revision 533)
@@ -0,0 +1,5163 @@
+/**
+ * @license
+ * Lo-Dash 1.0.1 <http://lodash.com/>
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function(window, undefined) {
+
+  /** Detect free variable `exports` */
+  var freeExports = typeof exports == 'object' && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
+
+  /** Detect free variable `global` and use it as `window` */
+  var freeGlobal = typeof global == 'object' && global;
+  if (freeGlobal.global === freeGlobal) {
+    window = freeGlobal;
+  }
+
+  /** Used for array and object method references */
+  var arrayRef = [],
+      objectRef = {};
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = objectRef;
+
+  /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
+  var largeArraySize = 30;
+
+  /** Used to restore the original `_` reference in `noConflict` */
+  var oldDash = window._;
+
+  /** Used to match HTML entities */
+  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detect if a method is native */
+  var reNative = RegExp('^' +
+    (objectRef.valueOf + '')
+      .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+      .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
+  );
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to match HTML characters */
+  var reUnescapedHtml = /[&<>"']/g;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to fix the JScript [[DontEnum]] bug */
+  var shadowed = [
+    'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+    'toLocaleString', 'toString', 'valueOf'
+  ];
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** Native method shortcuts */
+  var ceil = Math.ceil,
+      concat = arrayRef.concat,
+      floor = Math.floor,
+      getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+      hasOwnProperty = objectRef.hasOwnProperty,
+      push = arrayRef.push,
+      toString = objectRef.toString;
+
+  /* Native method shortcuts for methods with the same name as other `lodash` methods */
+  var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
+      nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
+      nativeIsFinite = window.isFinite,
+      nativeIsNaN = window.isNaN,
+      nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+      nativeMax = Math.max,
+      nativeMin = Math.min,
+      nativeRandom = Math.random;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Detect various environments */
+  var isIeOpera = !!window.attachEvent,
+      isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
+
+  /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
+  var isBindFast = nativeBind && !isV8;
+
+  /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
+  var isKeysFast = nativeKeys && (isIeOpera || isV8);
+
+  /**
+   * Detect the JScript [[DontEnum]] bug:
+   *
+   * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+   * made non-enumerable as well.
+   */
+  var hasDontEnumBug;
+
+  /**
+   * Detect if a `prototype` properties are enumerable by default:
+   *
+   * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+   * (if the prototype or a property on the prototype has been set)
+   * incorrectly sets a function's `prototype` property [[Enumerable]]
+   * value to `true`.
+   */
+  var hasEnumPrototype;
+
+  /** Detect if own properties are iterated after inherited properties (IE < 9) */
+  var iteratesOwnLast;
+
+  /**
+   * Detect if `Array#shift` and `Array#splice` augment array-like objects
+   * incorrectly:
+   *
+   * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+   * and `splice()` functions that fail to remove the last element, `value[0]`,
+   * of array-like objects even though the `length` property is set to `0`.
+   * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+   * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+   */
+  var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
+    arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
+
+  /** Detect if `arguments` object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1) */
+  var nonEnumArgs = true;
+
+  (function() {
+    var props = [];
+    function ctor() { this.x = 1; }
+    ctor.prototype = { 'valueOf': 1, 'y': 1 };
+    for (var prop in new ctor) { props.push(prop); }
+    for (prop in arguments) { nonEnumArgs = !prop; }
+
+    hasDontEnumBug = !/valueOf/.test(props);
+    hasEnumPrototype = ctor.propertyIsEnumerable('prototype');
+    iteratesOwnLast = props[0] != 'x';
+  }(1));
+
+  /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */
+  var argsAreObjects = arguments.constructor == Object;
+
+  /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */
+  var noArgsClass = !isArguments(arguments);
+
+  /**
+   * Detect lack of support for accessing string characters by index:
+   *
+   * IE < 8 can't access characters by index and IE 8 can only access
+   * characters by index on string literals.
+   */
+  var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
+
+  /**
+   * Detect if a DOM node's [[Class]] is unresolvable (IE < 9)
+   * and that the JS engine won't error when attempting to coerce an object to
+   * a string without a `toString` function.
+   */
+  try {
+    var noNodeClass = toString.call(document) == objectClass && !({ 'toString': 0 } + '');
+  } catch(e) { }
+
+  /** Used to identify object classifications that `_.clone` supports */
+  var cloneableClasses = {};
+  cloneableClasses[funcClass] = false;
+  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
+  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
+  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
+
+  /** Used to lookup a built-in constructor by [[Class]] */
+  var ctorByClass = {};
+  ctorByClass[arrayClass] = Array;
+  ctorByClass[boolClass] = Boolean;
+  ctorByClass[dateClass] = Date;
+  ctorByClass[objectClass] = Object;
+  ctorByClass[numberClass] = Number;
+  ctorByClass[regexpClass] = RegExp;
+  ctorByClass[stringClass] = String;
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object, that wraps the given `value`, to enable method
+   * chaining.
+   *
+   * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+   * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+   * and `unshift`
+   *
+   * The chainable wrapper functions are:
+   * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
+   * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
+   * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
+   * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
+   * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+   * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
+   * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
+   * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
+   *
+   * The non-chainable wrapper functions are:
+   * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
+   * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
+   * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
+   * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
+   * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
+   * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
+   *
+   * The wrapper functions `first` and `last` return wrapped values when `n` is
+   * passed, otherwise they return unwrapped values.
+   *
+   * @name _
+   * @constructor
+   * @category Chaining
+   * @param {Mixed} value The value to wrap in a `lodash` instance.
+   * @returns {Object} Returns a `lodash` instance.
+   */
+  function lodash(value) {
+    // exit early if already wrapped, even if wrapped by a different `lodash` constructor
+    if (value && typeof value == 'object' && value.__wrapped__) {
+      return value;
+    }
+    // allow invoking `lodash` without the `new` operator
+    if (!(this instanceof lodash)) {
+      return new lodash(value);
+    }
+    this.__wrapped__ = value;
+  }
+
+  /**
+   * By default, the template delimiters used by Lo-Dash are similar to those in
+   * embedded Ruby (ERB). Change the following template settings to use alternative
+   * delimiters.
+   *
+   * @static
+   * @memberOf _
+   * @type Object
+   */
+  lodash.templateSettings = {
+
+    /**
+     * Used to detect `data` property values to be HTML-escaped.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'escape': /<%-([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect code to be evaluated.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'evaluate': /<%([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect `data` property values to inject.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'interpolate': reInterpolate,
+
+    /**
+     * Used to reference the data object in the template text.
+     *
+     * @memberOf _.templateSettings
+     * @type String
+     */
+    'variable': '',
+
+    /**
+     * Used to import variables into the compiled template.
+     *
+     * @memberOf _.templateSettings
+     * @type Object
+     */
+    'imports': {
+
+      /**
+       * A reference to the `lodash` function.
+       *
+       * @memberOf _.templateSettings.imports
+       * @type Function
+       */
+      '_': lodash
+    }
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The template used to create iterator functions.
+   *
+   * @private
+   * @param {Obect} data The data object used to populate the text.
+   * @returns {String} Returns the interpolated text.
+   */
+  var iteratorTemplate = template(
+    // the `iterable` may be reassigned by the `top` snippet
+    'var index, iterable = <%= firstArg %>, ' +
+    // assign the `result` variable an initial value
+    'result = iterable;\n' +
+    // exit early if the first argument is falsey
+    'if (!iterable) return result;\n' +
+    // add code before the iteration branches
+    '<%= top %>;\n' +
+
+    // array-like iteration:
+    '<% if (arrays) { %>' +
+    'var length = iterable.length; index = -1;\n' +
+    'if (<%= arrays %>) {' +
+
+    // add support for accessing string characters by index if needed
+    '  <% if (noCharByIndex) { %>\n' +
+    '  if (isString(iterable)) {\n' +
+    "    iterable = iterable.split('')\n" +
+    '  }' +
+    '  <% } %>\n' +
+
+    // iterate over the array-like value
+    '  while (++index < length) {\n' +
+    '    <%= loop %>\n' +
+    '  }\n' +
+    '}\n' +
+    'else {' +
+
+    // object iteration:
+    // add support for iterating over `arguments` objects if needed
+    '  <%  } else if (nonEnumArgs) { %>\n' +
+    '  var length = iterable.length; index = -1;\n' +
+    '  if (length && isArguments(iterable)) {\n' +
+    '    while (++index < length) {\n' +
+    "      index += '';\n" +
+    '      <%= loop %>\n' +
+    '    }\n' +
+    '  } else {' +
+    '  <% } %>' +
+
+    // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari
+    '  <% if (hasEnumPrototype) { %>\n' +
+    "  var skipProto = typeof iterable == 'function';\n" +
+    '  <% } %>' +
+
+    // iterate own properties using `Object.keys` if it's fast
+    '  <% if (isKeysFast && useHas) { %>\n' +
+    '  var ownIndex = -1,\n' +
+    '      ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n' +
+    '      length = ownProps.length;\n\n' +
+    '  while (++ownIndex < length) {\n' +
+    '    index = ownProps[ownIndex];\n' +
+    "    <% if (hasEnumPrototype) { %>if (!(skipProto && index == 'prototype')) {\n  <% } %>" +
+    '    <%= loop %>\n' +
+    '    <% if (hasEnumPrototype) { %>}\n<% } %>' +
+    '  }' +
+
+    // else using a for-in loop
+    '  <% } else { %>\n' +
+    '  for (index in iterable) {<%' +
+    '    if (hasEnumPrototype || useHas) { %>\n    if (<%' +
+    "      if (hasEnumPrototype) { %>!(skipProto && index == 'prototype')<% }" +
+    '      if (hasEnumPrototype && useHas) { %> && <% }' +
+    '      if (useHas) { %>hasOwnProperty.call(iterable, index)<% }' +
+    '    %>) {' +
+    '    <% } %>\n' +
+    '    <%= loop %>;' +
+    '    <% if (hasEnumPrototype || useHas) { %>\n    }<% } %>\n' +
+    '  }' +
+    '  <% } %>' +
+
+    // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
+    // existing property and the `constructor` property of a prototype
+    // defaults to non-enumerable, Lo-Dash skips the `constructor`
+    // property when it infers it's iterating over a `prototype` object.
+    '  <% if (hasDontEnumBug) { %>\n\n' +
+    '  var ctor = iterable.constructor;\n' +
+    '    <% for (var k = 0; k < 7; k++) { %>\n' +
+    "  index = '<%= shadowed[k] %>';\n" +
+    '  if (<%' +
+    "      if (shadowed[k] == 'constructor') {" +
+    '        %>!(ctor && ctor.prototype === iterable) && <%' +
+    '      } %>hasOwnProperty.call(iterable, index)) {\n' +
+    '    <%= loop %>\n' +
+    '  }' +
+    '    <% } %>' +
+    '  <% } %>' +
+    '  <% if (arrays || nonEnumArgs) { %>\n}<% } %>\n' +
+
+    // add code to the bottom of the iteration function
+    '<%= bottom %>;\n' +
+    // finally, return the `result`
+    'return result'
+  );
+
+  /** Reusable iterator options for `assign` and `defaults` */
+  var defaultsIteratorOptions = {
+    'args': 'object, source, guard',
+    'top':
+      'var args = arguments,\n' +
+      '    argsIndex = 0,\n' +
+      "    argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
+      'while (++argsIndex < argsLength) {\n' +
+      '  iterable = args[argsIndex];\n' +
+      '  if (iterable && objectTypes[typeof iterable]) {',
+    'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
+    'bottom': '  }\n}'
+  };
+
+  /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
+  var eachIteratorOptions = {
+    'args': 'collection, callback, thisArg',
+    'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
+    'arrays': "typeof length == 'number'",
+    'loop': 'if (callback(iterable[index], index, collection) === false) return result'
+  };
+
+  /** Reusable iterator options for `forIn` and `forOwn` */
+  var forOwnIteratorOptions = {
+    'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
+    'arrays': false
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function optimized to search large arrays for a given `value`,
+   * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @param {Number} [largeSize=30] The length at which an array is considered large.
+   * @returns {Boolean} Returns `true`, if `value` is found, else `false`.
+   */
+  function cachedContains(array, fromIndex, largeSize) {
+    fromIndex || (fromIndex = 0);
+
+    var length = array.length,
+        isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
+
+    if (isLarge) {
+      var cache = {},
+          index = fromIndex - 1;
+
+      while (++index < length) {
+        // manually coerce `value` to a string because `hasOwnProperty`, in some
+        // older versions of Firefox, coerces objects incorrectly
+        var key = array[index] + '';
+        (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
+      }
+    }
+    return function(value) {
+      if (isLarge) {
+        var key = value + '';
+        return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
+      }
+      return indexOf(array, value, fromIndex) > -1;
+    }
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default `callback` when a given
+   * `collection` is a string value.
+   *
+   * @private
+   * @param {String} value The character to inspect.
+   * @returns {Number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` values, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {Number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ai = a.index,
+        bi = b.index;
+
+    a = a.criteria;
+    b = b.criteria;
+
+    // ensure a stable sort in V8 and other engines
+    // http://code.google.com/p/v8/issues/detail?id=90
+    if (a !== b) {
+      if (a > b || typeof a == 'undefined') {
+        return 1;
+      }
+      if (a < b || typeof b == 'undefined') {
+        return -1;
+      }
+    }
+    return ai < bi ? -1 : 1;
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this` binding
+   * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
+   * bound function.
+   *
+   * @private
+   * @param {Function|String} func The function to bind or the method name.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Array} partialArgs An array of arguments to be partially applied.
+   * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
+   * @returns {Function} Returns the new bound function.
+   */
+  function createBound(func, thisArg, partialArgs, rightIndicator) {
+    var isFunc = isFunction(func),
+        isPartial = !partialArgs,
+        key = thisArg;
+
+    // juggle arguments
+    if (isPartial) {
+      partialArgs = thisArg;
+    }
+    if (!isFunc) {
+      thisArg = func;
+    }
+
+    function bound() {
+      // `Function#bind` spec
+      // http://es5.github.com/#x15.3.4.5
+      var args = arguments,
+          thisBinding = isPartial ? this : thisArg;
+
+      if (!isFunc) {
+        func = thisArg[key];
+      }
+      if (partialArgs.length) {
+        args = args.length
+          ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
+          : partialArgs;
+      }
+      if (this instanceof bound) {
+        // ensure `new bound` is an instance of `bound` and `func`
+        noop.prototype = func.prototype;
+        thisBinding = new noop;
+        noop.prototype = null;
+
+        // mimic the constructor's `return` behavior
+        // http://es5.github.com/#x13.2.2
+        var result = func.apply(thisBinding, args);
+        return isObject(result) ? result : thisBinding;
+      }
+      return func.apply(thisBinding, args);
+    }
+    return bound;
+  }
+
+  /**
+   * Produces a callback bound to an optional `thisArg`. If `func` is a property
+   * name, the created callback will return the property value for a given element.
+   * If `func` is an object, the created callback will return `true` for elements
+   * that contain the equivalent object properties, otherwise it will return `false`.
+   *
+   * @private
+   * @param {Mixed} [func=identity] The value to convert to a callback.
+   * @param {Mixed} [thisArg] The `this` binding of the created callback.
+   * @param {Number} [argCount=3] The number of arguments the callback accepts.
+   * @returns {Function} Returns a callback function.
+   */
+  function createCallback(func, thisArg, argCount) {
+    if (func == null) {
+      return identity;
+    }
+    var type = typeof func;
+    if (type != 'function') {
+      if (type != 'object') {
+        return function(object) {
+          return object[func];
+        };
+      }
+      var props = keys(func);
+      return function(object) {
+        var length = props.length,
+            result = false;
+        while (length--) {
+          if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+    if (typeof thisArg != 'undefined') {
+      if (argCount === 1) {
+        return function(value) {
+          return func.call(thisArg, value);
+        };
+      }
+      if (argCount === 2) {
+        return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+      }
+      if (argCount === 4) {
+        return function(accumulator, value, index, object) {
+          return func.call(thisArg, accumulator, value, index, object);
+        };
+      }
+      return function(value, index, object) {
+        return func.call(thisArg, value, index, object);
+      };
+    }
+    return func;
+  }
+
+  /**
+   * Creates compiled iteration functions.
+   *
+   * @private
+   * @param {Object} [options1, options2, ...] The compile options object(s).
+   *  arrays - A string of code to determine if the iterable is an array or array-like.
+   *  useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
+   *  args - A string of comma separated arguments the iteration function will accept.
+   *  top - A string of code to execute before the iteration branches.
+   *  loop - A string of code to execute in the object loop.
+   *  bottom - A string of code to execute after the iteration branches.
+   *
+   * @returns {Function} Returns the compiled function.
+   */
+  function createIterator() {
+    var data = {
+      // support properties
+      'hasDontEnumBug': hasDontEnumBug,
+      'hasEnumPrototype': hasEnumPrototype,
+      'isKeysFast': isKeysFast,
+      'nonEnumArgs': nonEnumArgs,
+      'noCharByIndex': noCharByIndex,
+      'shadowed': shadowed,
+
+      // iterator options
+      'arrays': 'isArray(iterable)',
+      'bottom': '',
+      'loop': '',
+      'top': '',
+      'useHas': true
+    };
+
+    // merge options into a template data object
+    for (var object, index = 0; object = arguments[index]; index++) {
+      for (var key in object) {
+        data[key] = object[key];
+      }
+    }
+    var args = data.args;
+    data.firstArg = /^[^,]+/.exec(args)[0];
+
+    // create the function factory
+    var factory = Function(
+        'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
+        'objectTypes, nativeKeys',
+      'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
+    );
+    // return the compiled function
+    return factory(
+      createCallback, hasOwnProperty, isArguments, isArray, isString,
+      objectTypes, nativeKeys
+    );
+  }
+
+  /**
+   * A function compiled to iterate `arguments` objects, arrays, objects, and
+   * strings consistenly across environments, executing the `callback` for each
+   * element in the `collection`. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, index|key, collection). Callbacks may exit
+   * iteration early by explicitly returning `false`.
+   *
+   * @private
+   * @type Function
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   */
+  var each = createIterator(eachIteratorOptions);
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Used by `escape` to convert characters to HTML entities.
+   *
+   * @private
+   * @param {String} match The matched character to escape.
+   * @returns {String} Returns the escaped character.
+   */
+  function escapeHtmlChar(match) {
+    return htmlEscapes[match];
+  }
+
+  /**
+   * Checks if `value` is a DOM node in IE < 9.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
+   */
+  function isNode(value) {
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings
+    return typeof value.toString != 'function' && typeof (value + '') == 'string';
+  }
+
+  /**
+   * A no-operation function.
+   *
+   * @private
+   */
+  function noop() {
+    // no operation performed
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used, instead of `Array#slice`, to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|String} collection The collection to slice.
+   * @param {Number} start The start index.
+   * @param {Number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /**
+   * Used by `unescape` to convert HTML entities to characters.
+   *
+   * @private
+   * @param {String} match The matched character to unescape.
+   * @returns {String} Returns the unescaped character.
+   */
+  function unescapeHtmlChar(match) {
+    return htmlUnescapes[match];
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if `value` is an `arguments` object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
+   * @example
+   *
+   * (function() { return _.isArguments(arguments); })(1, 2, 3);
+   * // => true
+   *
+   * _.isArguments([1, 2, 3]);
+   * // => false
+   */
+  function isArguments(value) {
+    return toString.call(value) == argsClass;
+  }
+  // fallback for browsers that can't detect `arguments` objects by [[Class]]
+  if (noArgsClass) {
+    isArguments = function(value) {
+      return value ? hasOwnProperty.call(value, 'callee') : false;
+    };
+  }
+
+  /**
+   * Iterates over `object`'s own and inherited enumerable properties, executing
+   * the `callback` for each property. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, key, object). Callbacks may exit iteration
+   * early by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * function Dog(name) {
+   *   this.name = name;
+   * }
+   *
+   * Dog.prototype.bark = function() {
+   *   alert('Woof, woof!');
+   * };
+   *
+   * _.forIn(new Dog('Dagny'), function(value, key) {
+   *   alert(key);
+   * });
+   * // => alerts 'name' and 'bark' (order is not guaranteed)
+   */
+  var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
+    'useHas': false
+  });
+
+  /**
+   * Iterates over an object's own enumerable properties, executing the `callback`
+   * for each property. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
+   * returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+   *   alert(key);
+   * });
+   * // => alerts '0', '1', and 'length' (order is not guaranteed)
+   */
+  var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
+
+  /**
+   * Checks if `value` is an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
+   * @example
+   *
+   * (function() { return _.isArray(arguments); })();
+   * // => false
+   *
+   * _.isArray([1, 2, 3]);
+   * // => true
+   */
+  var isArray = nativeIsArray || function(value) {
+    // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
+    // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
+    return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass;
+  };
+
+  /**
+   * Creates an array composed of the own enumerable property names of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   * @example
+   *
+   * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => ['one', 'two', 'three'] (order is not guaranteed)
+   */
+  var keys = !nativeKeys ? shimKeys : function(object) {
+    if (!isObject(object)) {
+      return [];
+    }
+    if ((hasEnumPrototype && typeof object == 'function') ||
+        (nonEnumArgs && object.length && isArguments(object))) {
+      return shimKeys(object);
+    }
+    return nativeKeys(object);
+  };
+
+  /**
+   * A fallback implementation of `isPlainObject` that checks if a given `value`
+   * is an object created by the `Object` constructor, assuming objects created
+   * by the `Object` constructor have no inherited enumerable properties and that
+   * there are no `Object.prototype` extensions.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   */
+  function shimIsPlainObject(value) {
+    // avoid non-objects and false positives for `arguments` objects
+    var result = false;
+    if (!(value && typeof value == 'object') || isArguments(value)) {
+      return result;
+    }
+    // check that the constructor is `Object` (i.e. `Object instanceof Object`)
+    var ctor = value.constructor;
+    if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) {
+      // IE < 9 iterates inherited properties before own properties. If the first
+      // iterated property is an object's own property then there are no inherited
+      // enumerable properties.
+      if (iteratesOwnLast) {
+        forIn(value, function(value, key, object) {
+          result = !hasOwnProperty.call(object, key);
+          return false;
+        });
+        return result === false;
+      }
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return result === false || hasOwnProperty.call(value, result);
+    }
+    return result;
+  }
+
+  /**
+   * A fallback implementation of `Object.keys` that produces an array of the
+   * given object's own enumerable property names.
+   *
+   * @private
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names.
+   */
+  function shimKeys(object) {
+    var result = [];
+    forOwn(object, function(value, key) {
+      result.push(key);
+    });
+    return result;
+  }
+
+  /**
+   * Used to convert characters to HTML entities:
+   *
+   * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+   * don't require escaping in HTML and have no special meaning unless they're part
+   * of a tag or an unquoted attribute value.
+   * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+   */
+  var htmlEscapes = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#39;'
+  };
+
+  /** Used to convert HTML entities to characters */
+  var htmlUnescapes = invert(htmlEscapes);
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object. Subsequent sources will overwrite propery assignments of previous
+   * sources. If a `callback` function is passed, it will be executed to produce
+   * the assigned values. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @alias extend
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize assigning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * _.assign({ 'name': 'moe' }, { 'age': 40 });
+   * // => { 'name': 'moe', 'age': 40 }
+   *
+   * var defaults = _.partialRight(_.assign, function(a, b) {
+   *   return typeof a == 'undefined' ? b : a;
+   * });
+   *
+   * var food = { 'name': 'apple' };
+   * defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  var assign = createIterator(defaultsIteratorOptions, {
+    'top':
+      defaultsIteratorOptions.top.replace(';',
+        ';\n' +
+        "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
+        '  var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
+        "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
+        '  callback = args[--argsLength];\n' +
+        '}'
+      ),
+    'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
+  });
+
+  /**
+   * Creates a clone of `value`. If `deep` is `true`, nested objects will also
+   * be cloned, otherwise they will be assigned by reference. If a `callback`
+   * function is passed, it will be executed to produce the cloned values. If
+   * `callback` returns `undefined`, cloning will be handled by the method instead.
+   * The `callback` is bound to `thisArg` and invoked with one argument; (value).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to clone.
+   * @param {Boolean} [deep=false] A flag to indicate a deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
+   * @returns {Mixed} Returns the cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var shallow = _.clone(stooges);
+   * shallow[0] === stooges[0];
+   * // => true
+   *
+   * var deep = _.clone(stooges, true);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * _.mixin({
+   *   'clone': _.partialRight(_.clone, function(value) {
+   *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+   *   })
+   * });
+   *
+   * var clone = _.clone(document.body);
+   * clone.childNodes.length;
+   * // => 0
+   */
+  function clone(value, deep, callback, thisArg, stackA, stackB) {
+    var result = value;
+
+    // allows working with "Collections" methods without using their `callback`
+    // argument, `index|key`, for this method's `callback`
+    if (typeof deep == 'function') {
+      thisArg = callback;
+      callback = deep;
+      deep = false;
+    }
+    if (typeof callback == 'function') {
+      callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
+      result = callback(result);
+
+      var done = typeof result != 'undefined';
+      if (!done) {
+        result = value;
+      }
+    }
+    // inspect [[Class]]
+    var isObj = isObject(result);
+    if (isObj) {
+      var className = toString.call(result);
+      if (!cloneableClasses[className] || (noNodeClass && isNode(result))) {
+        return result;
+      }
+      var isArr = isArray(result);
+    }
+    // shallow clone
+    if (!isObj || !deep) {
+      return isObj && !done
+        ? (isArr ? slice(result) : assign({}, result))
+        : result;
+    }
+    var ctor = ctorByClass[className];
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        return done ? result : new ctor(+result);
+
+      case numberClass:
+      case stringClass:
+        return done ? result : new ctor(result);
+
+      case regexpClass:
+        return done ? result : ctor(result.source, reFlags.exec(result));
+    }
+    // check for circular references and return corresponding clone
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == value) {
+        return stackB[length];
+      }
+    }
+    // init cloned object
+    if (!done) {
+      result = isArr ? ctor(result.length) : {};
+
+      // add array properties assigned by `RegExp#exec`
+      if (isArr) {
+        if (hasOwnProperty.call(value, 'index')) {
+          result.index = value.index;
+        }
+        if (hasOwnProperty.call(value, 'input')) {
+          result.input = value.input;
+        }
+      }
+    }
+    // add the source value to the stack of traversed objects
+    // and associate it with its clone
+    stackA.push(value);
+    stackB.push(result);
+
+    // recursively populate clone (susceptible to call stack limits)
+    (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
+      result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
+    });
+
+    return result;
+  }
+
+  /**
+   * Creates a deep clone of `value`. If a `callback` function is passed, it will
+   * be executed to produce the cloned values. If `callback` returns the value it
+   * was passed, cloning will be handled by the method instead. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * Note: This function is loosely based on the structured clone algorithm. Functions
+   * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+   * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+   * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the deep cloned `value`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * var deep = _.cloneDeep(stooges);
+   * deep[0] === stooges[0];
+   * // => false
+   *
+   * var view = {
+   *   'label': 'docs',
+   *   'node': element
+   * };
+   *
+   * var clone = _.cloneDeep(view, function(value) {
+   *   return _.isElement(value) ? value.cloneNode(true) : value;
+   * });
+   *
+   * clone.node == view.node;
+   * // => false
+   */
+  function cloneDeep(value, callback, thisArg) {
+    return clone(value, true, callback, thisArg);
+  }
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object for all destination properties that resolve to `undefined`. Once a
+   * property is set, additional defaults of the same property will be ignored.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param- {Object} [guard] Internally used to allow working with `_.reduce`
+   *  without using its callback's `key` and `object` arguments as sources.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var food = { 'name': 'apple' };
+   * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
+   * // => { 'name': 'apple', 'type': 'fruit' }
+   */
+  var defaults = createIterator(defaultsIteratorOptions);
+
+  /**
+   * Creates a sorted array of all enumerable properties, own and inherited,
+   * of `object` that have function values.
+   *
+   * @static
+   * @memberOf _
+   * @alias methods
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property names that have function values.
+   * @example
+   *
+   * _.functions(_);
+   * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+   */
+  function functions(object) {
+    var result = [];
+    forIn(object, function(value, key) {
+      if (isFunction(value)) {
+        result.push(key);
+      }
+    });
+    return result.sort();
+  }
+
+  /**
+   * Checks if the specified object `property` exists and is a direct property,
+   * instead of an inherited property.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to check.
+   * @param {String} property The property to check for.
+   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+   * @example
+   *
+   * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+   * // => true
+   */
+  function has(object, property) {
+    return object ? hasOwnProperty.call(object, property) : false;
+  }
+
+  /**
+   * Creates an object composed of the inverted keys and values of the given `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to invert.
+   * @returns {Object} Returns the created inverted object.
+   * @example
+   *
+   *  _.invert({ 'first': 'moe', 'second': 'larry' });
+   * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
+   */
+  function invert(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      result[object[key]] = key;
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is a boolean value.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
+   * @example
+   *
+   * _.isBoolean(null);
+   * // => false
+   */
+  function isBoolean(value) {
+    return value === true || value === false || toString.call(value) == boolClass;
+  }
+
+  /**
+   * Checks if `value` is a date.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
+   * @example
+   *
+   * _.isDate(new Date);
+   * // => true
+   */
+  function isDate(value) {
+    return value instanceof Date || toString.call(value) == dateClass;
+  }
+
+  /**
+   * Checks if `value` is a DOM element.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
+   * @example
+   *
+   * _.isElement(document.body);
+   * // => true
+   */
+  function isElement(value) {
+    return value ? value.nodeType === 1 : false;
+  }
+
+  /**
+   * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+   * length of `0` and objects with no own enumerable properties are considered
+   * "empty".
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Array|Object|String} value The value to inspect.
+   * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
+   * @example
+   *
+   * _.isEmpty([1, 2, 3]);
+   * // => false
+   *
+   * _.isEmpty({});
+   * // => true
+   *
+   * _.isEmpty('');
+   * // => true
+   */
+  function isEmpty(value) {
+    var result = true;
+    if (!value) {
+      return result;
+    }
+    var className = toString.call(value),
+        length = value.length;
+
+    if ((className == arrayClass || className == stringClass ||
+        className == argsClass || (noArgsClass && isArguments(value))) ||
+        (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+      return !length;
+    }
+    forOwn(value, function() {
+      return (result = false);
+    });
+    return result;
+  }
+
+  /**
+   * Performs a deep comparison between two values to determine if they are
+   * equivalent to each other. If `callback` is passed, it will be executed to
+   * compare values. If `callback` returns `undefined`, comparisons will be handled
+   * by the method instead. The `callback` is bound to `thisArg` and invoked with
+   * two arguments; (a, b).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} a The value to compare.
+   * @param {Mixed} b The other value to compare.
+   * @param {Function} [callback] The function to customize comparing values.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
+   * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
+   * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
+   * @example
+   *
+   * var moe = { 'name': 'moe', 'age': 40 };
+   * var copy = { 'name': 'moe', 'age': 40 };
+   *
+   * moe == copy;
+   * // => false
+   *
+   * _.isEqual(moe, copy);
+   * // => true
+   *
+   * var words = ['hello', 'goodbye'];
+   * var otherWords = ['hi', 'goodbye'];
+   *
+   * _.isEqual(words, otherWords, function(a, b) {
+   *   var reGreet = /^(?:hello|hi)$/i,
+   *       aGreet = _.isString(a) && reGreet.test(a),
+   *       bGreet = _.isString(b) && reGreet.test(b);
+   *
+   *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+   * });
+   * // => true
+   */
+  function isEqual(a, b, callback, thisArg, stackA, stackB) {
+    // used to indicate that when comparing objects, `a` has at least the properties of `b`
+    var whereIndicator = callback === indicatorObject;
+    if (callback && !whereIndicator) {
+      callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
+      var result = callback(a, b);
+      if (typeof result != 'undefined') {
+        return !!result;
+      }
+    }
+    // exit early for identical values
+    if (a === b) {
+      // treat `+0` vs. `-0` as not equal
+      return a !== 0 || (1 / a == 1 / b);
+    }
+    var type = typeof a,
+        otherType = typeof b;
+
+    // exit early for unlike primitive values
+    if (a === a &&
+        (!a || (type != 'function' && type != 'object')) &&
+        (!b || (otherType != 'function' && otherType != 'object'))) {
+      return false;
+    }
+    // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
+    // http://es5.github.com/#x15.3.4.4
+    if (a == null || b == null) {
+      return a === b;
+    }
+    // compare [[Class]] names
+    var className = toString.call(a),
+        otherClass = toString.call(b);
+
+    if (className == argsClass) {
+      className = objectClass;
+    }
+    if (otherClass == argsClass) {
+      otherClass = objectClass;
+    }
+    if (className != otherClass) {
+      return false;
+    }
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        // coerce dates and booleans to numbers, dates to milliseconds and booleans
+        // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
+        return +a == +b;
+
+      case numberClass:
+        // treat `NaN` vs. `NaN` as equal
+        return a != +a
+          ? b != +b
+          // but treat `+0` vs. `-0` as not equal
+          : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+      case regexpClass:
+      case stringClass:
+        // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
+        // treat string primitives and their corresponding object instances as equal
+        return a == b + '';
+    }
+    var isArr = className == arrayClass;
+    if (!isArr) {
+      // unwrap any `lodash` wrapped values
+      if (a.__wrapped__ || b.__wrapped__) {
+        return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
+      }
+      // exit for functions and DOM nodes
+      if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) {
+        return false;
+      }
+      // in older versions of Opera, `arguments` objects have `Array` constructors
+      var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor,
+          ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor;
+
+      // non `Object` object instances with different constructors are not equal
+      if (ctorA != ctorB && !(
+            isFunction(ctorA) && ctorA instanceof ctorA &&
+            isFunction(ctorB) && ctorB instanceof ctorB
+          )) {
+        return false;
+      }
+    }
+    // assume cyclic structures are equal
+    // the algorithm for detecting cyclic structures is adapted from ES 5.1
+    // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == a) {
+        return stackB[length] == b;
+      }
+    }
+    var size = 0;
+    result = true;
+
+    // add `a` and `b` to the stack of traversed objects
+    stackA.push(a);
+    stackB.push(b);
+
+    // recursively compare objects and arrays (susceptible to call stack limits)
+    if (isArr) {
+      length = a.length;
+      size = b.length;
+
+      // compare lengths to determine if a deep comparison is necessary
+      result = size == a.length;
+      if (!result && !whereIndicator) {
+        return result;
+      }
+      // deep compare the contents, ignoring non-numeric properties
+      while (size--) {
+        var index = length,
+            value = b[size];
+
+        if (whereIndicator) {
+          while (index--) {
+            if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
+              break;
+            }
+          }
+        } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
+          break;
+        }
+      }
+      return result;
+    }
+    // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
+    // which, in this case, is more costly
+    forIn(b, function(value, key, b) {
+      if (hasOwnProperty.call(b, key)) {
+        // count the number of properties.
+        size++;
+        // deep compare each property value.
+        return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
+      }
+    });
+
+    if (result && !whereIndicator) {
+      // ensure both objects have the same number of properties
+      forIn(a, function(value, key, a) {
+        if (hasOwnProperty.call(a, key)) {
+          // `size` will be `-1` if `a` has more properties than `b`
+          return (result = --size > -1);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is, or can be coerced to, a finite number.
+   *
+   * Note: This is not the same as native `isFinite`, which will return true for
+   * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
+   * @example
+   *
+   * _.isFinite(-101);
+   * // => true
+   *
+   * _.isFinite('10');
+   * // => true
+   *
+   * _.isFinite(true);
+   * // => false
+   *
+   * _.isFinite('');
+   * // => false
+   *
+   * _.isFinite(Infinity);
+   * // => false
+   */
+  function isFinite(value) {
+    return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+  }
+
+  /**
+   * Checks if `value` is a function.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
+   * @example
+   *
+   * _.isFunction(_);
+   * // => true
+   */
+  function isFunction(value) {
+    return typeof value == 'function';
+  }
+  // fallback for older versions of Chrome and Safari
+  if (isFunction(/x/)) {
+    isFunction = function(value) {
+      return value instanceof Function || toString.call(value) == funcClass;
+    };
+  }
+
+  /**
+   * Checks if `value` is the language type of Object.
+   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
+   * @example
+   *
+   * _.isObject({});
+   * // => true
+   *
+   * _.isObject([1, 2, 3]);
+   * // => true
+   *
+   * _.isObject(1);
+   * // => false
+   */
+  function isObject(value) {
+    // check if the value is the ECMAScript language type of Object
+    // http://es5.github.com/#x8
+    // and avoid a V8 bug
+    // http://code.google.com/p/v8/issues/detail?id=2291
+    return value ? objectTypes[typeof value] : false;
+  }
+
+  /**
+   * Checks if `value` is `NaN`.
+   *
+   * Note: This is not the same as native `isNaN`, which will return `true` for
+   * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
+   * @example
+   *
+   * _.isNaN(NaN);
+   * // => true
+   *
+   * _.isNaN(new Number(NaN));
+   * // => true
+   *
+   * isNaN(undefined);
+   * // => true
+   *
+   * _.isNaN(undefined);
+   * // => false
+   */
+  function isNaN(value) {
+    // `NaN` as a primitive is the only value that is not equal to itself
+    // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+    return isNumber(value) && value != +value
+  }
+
+  /**
+   * Checks if `value` is `null`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
+   * @example
+   *
+   * _.isNull(null);
+   * // => true
+   *
+   * _.isNull(undefined);
+   * // => false
+   */
+  function isNull(value) {
+    return value === null;
+  }
+
+  /**
+   * Checks if `value` is a number.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
+   * @example
+   *
+   * _.isNumber(8.4 * 5);
+   * // => true
+   */
+  function isNumber(value) {
+    return typeof value == 'number' || toString.call(value) == numberClass;
+  }
+
+  /**
+   * Checks if a given `value` is an object created by the `Object` constructor.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
+   * @example
+   *
+   * function Stooge(name, age) {
+   *   this.name = name;
+   *   this.age = age;
+   * }
+   *
+   * _.isPlainObject(new Stooge('moe', 40));
+   * // => false
+   *
+   * _.isPlainObject([1, 2, 3]);
+   * // => false
+   *
+   * _.isPlainObject({ 'name': 'moe', 'age': 40 });
+   * // => true
+   */
+  var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+    if (!(value && typeof value == 'object')) {
+      return false;
+    }
+    var valueOf = value.valueOf,
+        objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+    return objProto
+      ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
+      : shimIsPlainObject(value);
+  };
+
+  /**
+   * Checks if `value` is a regular expression.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
+   * @example
+   *
+   * _.isRegExp(/moe/);
+   * // => true
+   */
+  function isRegExp(value) {
+    return value instanceof RegExp || toString.call(value) == regexpClass;
+  }
+
+  /**
+   * Checks if `value` is a string.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
+   * @example
+   *
+   * _.isString('moe');
+   * // => true
+   */
+  function isString(value) {
+    return typeof value == 'string' || toString.call(value) == stringClass;
+  }
+
+  /**
+   * Checks if `value` is `undefined`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
+   * @example
+   *
+   * _.isUndefined(void 0);
+   * // => true
+   */
+  function isUndefined(value) {
+    return typeof value == 'undefined';
+  }
+
+  /**
+   * Recursively merges own enumerable properties of the source object(s), that
+   * don't resolve to `undefined`, into the destination object. Subsequent sources
+   * will overwrite propery assignments of previous sources. If a `callback` function
+   * is passed, it will be executed to produce the merged values of the destination
+   * and source properties. If `callback` returns `undefined`, merging will be
+   * handled by the method instead. The `callback` is bound to `thisArg` and
+   * invoked with two arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {Object} [source1, source2, ...] The source objects.
+   * @param {Function} [callback] The function to customize merging properties.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @param- {Object} [deepIndicator] Internally used to indicate that `stackA`
+   *  and `stackB` are arrays of traversed objects instead of source objects.
+   * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+   * @param- {Array} [stackB=[]] Internally used to associate values with their
+   *  source counterparts.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var names = {
+   *   'stooges': [
+   *     { 'name': 'moe' },
+   *     { 'name': 'larry' }
+   *   ]
+   * };
+   *
+   * var ages = {
+   *   'stooges': [
+   *     { 'age': 40 },
+   *     { 'age': 50 }
+   *   ]
+   * };
+   *
+   * _.merge(names, ages);
+   * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
+   *
+   * var food = {
+   *   'fruits': ['apple'],
+   *   'vegetables': ['beet']
+   * };
+   *
+   * var otherFood = {
+   *   'fruits': ['banana'],
+   *   'vegetables': ['carrot']
+   * };
+   *
+   * _.merge(food, otherFood, function(a, b) {
+   *   return _.isArray(a) ? a.concat(b) : undefined;
+   * });
+   * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+   */
+  function merge(object, source, deepIndicator) {
+    var args = arguments,
+        index = 0,
+        length = 2;
+
+    if (!isObject(object)) {
+      return object;
+    }
+    if (deepIndicator === indicatorObject) {
+      var callback = args[3],
+          stackA = args[4],
+          stackB = args[5];
+    } else {
+      stackA = [];
+      stackB = [];
+
+      // allows working with `_.reduce` and `_.reduceRight` without
+      // using their `callback` arguments, `index|key` and `collection`
+      if (typeof deepIndicator != 'number') {
+        length = args.length;
+      }
+      if (length > 3 && typeof args[length - 2] == 'function') {
+        callback = createCallback(args[--length - 1], args[length--], 2);
+      } else if (length > 2 && typeof args[length - 1] == 'function') {
+        callback = args[--length];
+      }
+    }
+    while (++index < length) {
+      (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
+        var found,
+            isArr,
+            result = source,
+            value = object[key];
+
+        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+          // avoid merging previously merged cyclic sources
+          var stackLength = stackA.length;
+          while (stackLength--) {
+            if ((found = stackA[stackLength] == source)) {
+              value = stackB[stackLength];
+              break;
+            }
+          }
+          if (!found) {
+            value = isArr
+              ? (isArray(value) ? value : [])
+              : (isPlainObject(value) ? value : {});
+
+            if (callback) {
+              result = callback(value, source);
+              if (typeof result != 'undefined') {
+                value = result;
+              }
+            }
+            // add `source` and associated `value` to the stack of traversed objects
+            stackA.push(source);
+            stackB.push(value);
+
+            // recursively merge objects and arrays (susceptible to call stack limits)
+            if (!callback) {
+              value = merge(value, source, indicatorObject, callback, stackA, stackB);
+            }
+          }
+        }
+        else {
+          if (callback) {
+            result = callback(value, source);
+            if (typeof result == 'undefined') {
+              result = source;
+            }
+          }
+          if (typeof result != 'undefined') {
+            value = result;
+          }
+        }
+        object[key] = value;
+      });
+    }
+    return object;
+  }
+
+  /**
+   * Creates a shallow clone of `object` excluding the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a `callback` function is passed, it will be executed
+   * for each property in the `object`, omitting the properties `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked
+   * with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
+   *  or the function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object without the omitted properties.
+   * @example
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, 'age');
+   * // => { 'name': 'moe' }
+   *
+   * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
+   *   return typeof value == 'number';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function omit(object, callback, thisArg) {
+    var isFunc = typeof callback == 'function',
+        result = {};
+
+    if (isFunc) {
+      callback = createCallback(callback, thisArg);
+    } else {
+      var props = concat.apply(arrayRef, arguments);
+    }
+    forIn(object, function(value, key, object) {
+      if (isFunc
+            ? !callback(value, key, object)
+            : indexOf(props, key, 1) < 0
+          ) {
+        result[key] = value;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Creates a two dimensional array of the given object's key-value pairs,
+   * i.e. `[[key1, value1], [key2, value2]]`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns new array of key-value pairs.
+   * @example
+   *
+   * _.pairs({ 'moe': 30, 'larry': 40 });
+   * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
+   */
+  function pairs(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      var key = props[index];
+      result[index] = [key, object[key]];
+    }
+    return result;
+  }
+
+  /**
+   * Creates a shallow clone of `object` composed of the specified properties.
+   * Property names may be specified as individual arguments or as arrays of property
+   * names. If `callback` is passed, it will be executed for each property in the
+   * `object`, picking the properties `callback` returns truthy for. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
+   *  per iteration or properties to pick, either as individual arguments or arrays.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object composed of the picked properties.
+   * @example
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
+   * // => { 'name': 'moe' }
+   *
+   * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
+   *   return key.charAt(0) != '_';
+   * });
+   * // => { 'name': 'moe' }
+   */
+  function pick(object, callback, thisArg) {
+    var result = {};
+    if (typeof callback != 'function') {
+      var index = 0,
+          props = concat.apply(arrayRef, arguments),
+          length = isObject(object) ? props.length : 0;
+
+      while (++index < length) {
+        var key = props[index];
+        if (key in object) {
+          result[key] = object[key];
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg);
+      forIn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result[key] = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array composed of the own enumerable property values of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => [1, 2, 3]
+   */
+  function values(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = object[props[index]];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array of elements from the specified indexes, or keys, of the
+   * `collection`. Indexes may be specified as individual arguments or as arrays
+   * of indexes.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Array|Number|String} [index1, index2, ...] The indexes of
+   *  `collection` to retrieve, either as individual arguments or arrays.
+   * @returns {Array} Returns a new array of elements corresponding to the
+   *  provided indexes.
+   * @example
+   *
+   * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+   * // => ['a', 'c', 'e']
+   *
+   * _.at(['moe', 'larry', 'curly'], 0, 2);
+   * // => ['moe', 'curly']
+   */
+  function at(collection) {
+    var index = -1,
+        props = concat.apply(arrayRef, slice(arguments, 1)),
+        length = props.length,
+        result = Array(length);
+
+    if (noCharByIndex && isString(collection)) {
+      collection = collection.split('');
+    }
+    while(++index < length) {
+      result[index] = collection[props[index]];
+    }
+    return result;
+  }
+
+  /**
+   * Checks if a given `target` element is present in a `collection` using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @alias include
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Mixed} target The value to check for.
+   * @param {Number} [fromIndex=0] The index to search from.
+   * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
+   * @example
+   *
+   * _.contains([1, 2, 3], 1);
+   * // => true
+   *
+   * _.contains([1, 2, 3], 1, 2);
+   * // => false
+   *
+   * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+   * // => true
+   *
+   * _.contains('curly', 'ur');
+   * // => true
+   */
+  function contains(collection, target, fromIndex) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = false;
+
+    fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+    if (typeof length == 'number') {
+      result = (isString(collection)
+        ? collection.indexOf(target, fromIndex)
+        : indexOf(collection, target, fromIndex)
+      ) > -1;
+    } else {
+      each(collection, function(value) {
+        if (++index >= fromIndex) {
+          return !(result = value === target);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the given `callback`. The corresponding value of each key
+   * is the number of times the key was returned by the `callback`. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy(['one', 'two', 'three'], 'length');
+   * // => { '3': 2, '5': 1 }
+   */
+  function countBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+    return result;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **all** elements of a
+   * `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias all
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if all elements pass the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.every([true, 1, null, 'yes'], Boolean);
+   * // => false
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.every(stooges, 'age');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.every(stooges, { 'age': 50 });
+   * // => false
+   */
+  function every(collection, callback, thisArg) {
+    var result = true;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (!(result = !!callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return (result = !!callback(value, index, collection));
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
+   * invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias select
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that passed the callback check.
+   * @example
+   *
+   * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [2, 4, 6]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.filter(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.filter(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   */
+  function filter(collection, callback, thisArg) {
+    var result = [];
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Examines each element in a `collection`, returning the first that the `callback`
+   * returns truthy for. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias detect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the element that passed the callback check,
+   *  else `undefined`.
+   * @example
+   *
+   * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => 2
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },
+   *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * var veggie = _.find(food, { 'type': 'vegetable' });
+   * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
+   *
+   * // using "_.pluck" callback shorthand
+   * var healthy = _.find(food, 'organic');
+   * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
+   */
+  function find(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, index, collection) {
+      if (callback(value, index, collection)) {
+        result = value;
+        return false;
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Iterates over a `collection`, executing the `callback` for each element in
+   * the `collection`. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection). Callbacks may exit iteration early
+   * by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias each
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|String} Returns `collection`.
+   * @example
+   *
+   * _([1, 2, 3]).forEach(alert).join(',');
+   * // => alerts each number and returns '1,2,3'
+   *
+   * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
+   * // => alerts each number value (order is not guaranteed)
+   */
+  function forEach(collection, callback, thisArg) {
+    if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if (callback(collection[index], index, collection) === false) {
+          break;
+        }
+      }
+    } else {
+      each(collection, callback, thisArg);
+    }
+    return collection;
+  }
+
+  /**
+   * Creates an object composed of keys returned from running each element of the
+   * `collection` through the `callback`. The corresponding value of each key is
+   * an array of elements passed to `callback` that returned the key. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * // using "_.pluck" callback shorthand
+   * _.groupBy(['one', 'two', 'three'], 'length');
+   * // => { '3': ['one', 'two'], '5': ['three'] }
+   */
+  function groupBy(collection, callback, thisArg) {
+    var result = {};
+    callback = createCallback(callback, thisArg);
+
+    forEach(collection, function(value, key, collection) {
+      key = callback(value, key, collection) + '';
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+    return result;
+  }
+
+  /**
+   * Invokes the method named by `methodName` on each element in the `collection`,
+   * returning an array of the results of each invoked method. Additional arguments
+   * will be passed to each invoked method. If `methodName` is a function, it will
+   * be invoked for, and `this` bound to, each element in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|String} methodName The name of the method to invoke or
+   *  the function invoked per iteration.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+   * @returns {Array} Returns a new array of the results of each invoked method.
+   * @example
+   *
+   * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+   * // => [[1, 5, 7], [1, 2, 3]]
+   *
+   * _.invoke([123, 456], String.prototype.split, '');
+   * // => [['1', '2', '3'], ['4', '5', '6']]
+   */
+  function invoke(collection, methodName) {
+    var args = slice(arguments, 2),
+        index = -1,
+        isFunc = typeof methodName == 'function',
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+    });
+    return result;
+  }
+
+  /**
+   * Creates an array of values by running each element in the `collection`
+   * through the `callback`. The `callback` is bound to `thisArg` and invoked with
+   * three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias collect
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * _.map([1, 2, 3], function(num) { return num * 3; });
+   * // => [3, 6, 9]
+   *
+   * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+   * // => [3, 6, 9] (order is not guaranteed)
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.map(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  function map(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    if (isArray(collection)) {
+      while (++index < length) {
+        result[index] = callback(collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, key, collection) {
+        result[++index] = callback(value, key, collection);
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the maximum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the maximum value.
+   * @example
+   *
+   * _.max([4, 2, 8, 6]);
+   * // => 8
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.max(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'larry', 'age': 50 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.max(stooges, 'age');
+   * // => { 'name': 'larry', 'age': 50 };
+   */
+  function max(collection, callback, thisArg) {
+    var computed = -Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value > result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = !callback && isString(collection)
+        ? charAtCallback
+        : createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current > computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the minimum value of an `array`. If `callback` is passed,
+   * it will be executed for each value in the `array` to generate the
+   * criterion by which the value is ranked. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the minimum value.
+   * @example
+   *
+   * _.min([4, 2, 8, 6]);
+   * // => 2
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.min(stooges, function(stooge) { return stooge.age; });
+   * // => { 'name': 'moe', 'age': 40 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.min(stooges, 'age');
+   * // => { 'name': 'moe', 'age': 40 };
+   */
+  function min(collection, callback, thisArg) {
+    var computed = Infinity,
+        result = computed;
+
+    if (!callback && isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        var value = collection[index];
+        if (value < result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = !callback && isString(collection)
+        ? charAtCallback
+        : createCallback(callback, thisArg);
+
+      each(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current < computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the value of a specified property from all elements in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {String} property The property to pluck.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.pluck(stooges, 'name');
+   * // => ['moe', 'larry']
+   */
+  var pluck = map;
+
+  /**
+   * Reduces a `collection` to a value that is the accumulated result of running
+   * each element in the `collection` through the `callback`, where each successive
+   * `callback` execution consumes the return value of the previous execution.
+   * If `accumulator` is not passed, the first element of the `collection` will be
+   * used as the initial `accumulator` value. The `callback` is bound to `thisArg`
+   * and invoked with four arguments; (accumulator, value, index|key, collection).
+   *
+   * @static
+   * @memberOf _
+   * @alias foldl, inject
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var sum = _.reduce([1, 2, 3], function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+   *   result[key] = num * 3;
+   *   return result;
+   * }, {});
+   * // => { 'a': 3, 'b': 6, 'c': 9 }
+   */
+  function reduce(collection, callback, accumulator, thisArg) {
+    var noaccum = arguments.length < 3;
+    callback = createCallback(callback, thisArg, 4);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      if (noaccum) {
+        accumulator = collection[++index];
+      }
+      while (++index < length) {
+        accumulator = callback(accumulator, collection[index], index, collection);
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection)
+      });
+    }
+    return accumulator;
+  }
+
+  /**
+   * This method is similar to `_.reduce`, except that it iterates over a
+   * `collection` from right to left.
+   *
+   * @static
+   * @memberOf _
+   * @alias foldr
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {Mixed} [accumulator] Initial value of the accumulator.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the accumulated value.
+   * @example
+   *
+   * var list = [[0, 1], [2, 3], [4, 5]];
+   * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+   * // => [4, 5, 2, 3, 0, 1]
+   */
+  function reduceRight(collection, callback, accumulator, thisArg) {
+    var iterable = collection,
+        length = collection ? collection.length : 0,
+        noaccum = arguments.length < 3;
+
+    if (typeof length != 'number') {
+      var props = keys(collection);
+      length = props.length;
+    } else if (noCharByIndex && isString(collection)) {
+      iterable = collection.split('');
+    }
+    callback = createCallback(callback, thisArg, 4);
+    forEach(collection, function(value, index, collection) {
+      index = props ? props[--length] : --length;
+      accumulator = noaccum
+        ? (noaccum = false, iterable[index])
+        : callback(accumulator, iterable[index], index, collection);
+    });
+    return accumulator;
+  }
+
+  /**
+   * The opposite of `_.filter`, this method returns the elements of a
+   * `collection` that `callback` does **not** return truthy for.
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that did **not** pass the
+   *  callback check.
+   * @example
+   *
+   * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [1, 3, 5]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.reject(food, 'organic');
+   * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.reject(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
+   */
+  function reject(collection, callback, thisArg) {
+    callback = createCallback(callback, thisArg);
+    return filter(collection, function(value, index, collection) {
+      return !callback(value, index, collection);
+    });
+  }
+
+  /**
+   * Creates an array of shuffled `array` values, using a version of the
+   * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to shuffle.
+   * @returns {Array} Returns a new shuffled collection.
+   * @example
+   *
+   * _.shuffle([1, 2, 3, 4, 5, 6]);
+   * // => [4, 1, 6, 3, 5, 2]
+   */
+  function shuffle(collection) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      var rand = floor(nativeRandom() * (++index + 1));
+      result[index] = result[rand];
+      result[rand] = value;
+    });
+    return result;
+  }
+
+  /**
+   * Gets the size of the `collection` by returning `collection.length` for arrays
+   * and array-like objects or the number of own enumerable properties for objects.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to inspect.
+   * @returns {Number} Returns `collection.length` or number of own enumerable properties.
+   * @example
+   *
+   * _.size([1, 2]);
+   * // => 2
+   *
+   * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => 3
+   *
+   * _.size('curly');
+   * // => 5
+   */
+  function size(collection) {
+    var length = collection ? collection.length : 0;
+    return typeof length == 'number' ? length : keys(collection).length;
+  }
+
+  /**
+   * Checks if the `callback` returns a truthy value for **any** element of a
+   * `collection`. The function returns as soon as it finds passing value, and
+   * does not iterate over the entire `collection`. The `callback` is bound to
+   * `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias any
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Boolean} Returns `true` if any element passes the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.some([null, 0, 'yes', false], Boolean);
+   * // => true
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.some(food, 'organic');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.some(food, { 'type': 'meat' });
+   * // => false
+   */
+  function some(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      while (++index < length) {
+        if ((result = callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      each(collection, function(value, index, collection) {
+        return !(result = callback(value, index, collection));
+      });
+    }
+    return !!result;
+  }
+
+  /**
+   * Creates an array of elements, sorted in ascending order by the results of
+   * running each element in the `collection` through the `callback`. This method
+   * performs a stable sort, that is, it will preserve the original sort order of
+   * equal elements. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of sorted elements.
+   * @example
+   *
+   * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+   * // => [3, 1, 2]
+   *
+   * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+   * // => [3, 1, 2]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
+   * // => ['apple', 'banana', 'strawberry']
+   */
+  function sortBy(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg);
+    forEach(collection, function(value, key, collection) {
+      result[++index] = {
+        'criteria': callback(value, key, collection),
+        'index': index,
+        'value': value
+      };
+    });
+
+    length = result.length;
+    result.sort(compareAscending);
+    while (length--) {
+      result[length] = result[length].value;
+    }
+    return result;
+  }
+
+  /**
+   * Converts the `collection` to an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to convert.
+   * @returns {Array} Returns the new converted array.
+   * @example
+   *
+   * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+   * // => [2, 3, 4]
+   */
+  function toArray(collection) {
+    if (collection && typeof collection.length == 'number') {
+      return noCharByIndex && isString(collection)
+        ? collection.split('')
+        : slice(collection);
+    }
+    return values(collection);
+  }
+
+  /**
+   * Examines each element in a `collection`, returning an array of all elements
+   * that have the given `properties`. When checking `properties`, this method
+   * performs a deep comparison between values to determine if they are equivalent
+   * to each other.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|String} collection The collection to iterate over.
+   * @param {Object} properties The object of property values to filter by.
+   * @returns {Array} Returns a new array of elements that have the given `properties`.
+   * @example
+   *
+   * var stooges = [
+   *   { 'name': 'moe', 'age': 40 },
+   *   { 'name': 'larry', 'age': 50 }
+   * ];
+   *
+   * _.where(stooges, { 'age': 40 });
+   * // => [{ 'name': 'moe', 'age': 40 }]
+   */
+  var where = filter;
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array with all falsey values of `array` removed. The values
+   * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.compact([0, 1, false, 2, '', 3]);
+   * // => [1, 2, 3]
+   */
+  function compact(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (value) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of `array` elements not present in the other arrays
+   * using strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Array} [array1, array2, ...] Arrays to check.
+   * @returns {Array} Returns a new array of `array` elements not present in the
+   *  other arrays.
+   * @example
+   *
+   * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+   * // => [1, 3, 4]
+   */
+  function difference(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        flattened = concat.apply(arrayRef, arguments),
+        contains = cachedContains(flattened, length),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (!contains(value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the first element of the `array`. If a number `n` is passed, the first
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the first elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias head, take
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the first element(s) of `array`.
+   * @example
+   *
+   * _.first([1, 2, 3]);
+   * // => 1
+   *
+   * _.first([1, 2, 3], 2);
+   * // => [1, 2]
+   *
+   * _.first([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [1, 2]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.first(food, 'organic');
+   * // => [{ 'name': 'banana', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.first(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
+   */
+  function first(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = createCallback(callback, thisArg);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[0];
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+  }
+
+  /**
+   * Flattens a nested array (the nesting can be to any depth). If `shallow` is
+   * truthy, `array` will only be flattened a single level.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @param {Boolean} shallow A flag to indicate only flattening a single level.
+   * @returns {Array} Returns a new flattened array.
+   * @example
+   *
+   * _.flatten([1, [2], [3, [[4]]]]);
+   * // => [1, 2, 3, 4];
+   *
+   * _.flatten([1, [2], [3, [[4]]]], true);
+   * // => [1, 2, 3, [[4]]];
+   */
+  function flatten(array, shallow) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+
+      // recursively flatten arrays (susceptible to call stack limits)
+      if (isArray(value)) {
+        push.apply(result, shallow ? value : flatten(value));
+      } else {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the index at which the first occurrence of `value` is found using
+   * strict equality for comparisons, i.e. `===`. If the `array` is already
+   * sorted, passing `true` for `fromIndex` will run a faster binary search.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
+   *  perform a binary search on a sorted `array`.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 1
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 4
+   *
+   * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+   * // => 2
+   */
+  function indexOf(array, value, fromIndex) {
+    var index = -1,
+        length = array ? array.length : 0;
+
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
+    } else if (fromIndex) {
+      index = sortedIndex(array, value);
+      return array[index] === value ? index : -1;
+    }
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Gets all but the last element of `array`. If a number `n` is passed, the
+   * last `n` elements are excluded from the result. If a `callback` function
+   * is passed, the last elements the `callback` returns truthy for are excluded
+   * from the result. The `callback` is bound to `thisArg` and invoked with three
+   * arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.initial([1, 2, 3]);
+   * // => [1, 2]
+   *
+   * _.initial([1, 2, 3], 2);
+   * // => [1]
+   *
+   * _.initial([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [1]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.initial(food, 'organic');
+   * // => [{ 'name': 'beet',   'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.initial(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'banana', 'type': 'fruit' }]
+   */
+  function initial(array, callback, thisArg) {
+    if (!array) {
+      return [];
+    }
+    var n = 0,
+        length = array.length;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = length;
+      callback = createCallback(callback, thisArg);
+      while (index-- && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : callback || n;
+    }
+    return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+  }
+
+  /**
+   * Computes the intersection of all the passed-in arrays using strict equality
+   * for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique elements that are present
+   *  in **all** of the arrays.
+   * @example
+   *
+   * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2]
+   */
+  function intersection(array) {
+    var args = arguments,
+        argsLength = args.length,
+        cache = { '0': {} },
+        index = -1,
+        length = array ? array.length : 0,
+        isLarge = length >= 100,
+        result = [],
+        seen = result;
+
+    outer:
+    while (++index < length) {
+      var value = array[index];
+      if (isLarge) {
+        var key = value + '';
+        var inited = hasOwnProperty.call(cache[0], key)
+          ? !(seen = cache[0][key])
+          : (seen = cache[0][key] = []);
+      }
+      if (inited || indexOf(seen, value) < 0) {
+        if (isLarge) {
+          seen.push(value);
+        }
+        var argsIndex = argsLength;
+        while (--argsIndex) {
+          if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {
+            continue outer;
+          }
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the last element of the `array`. If a number `n` is passed, the last
+   * `n` elements of the `array` are returned. If a `callback` function is passed,
+   * the last elements the `callback` returns truthy for are returned. The `callback`
+   * is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Mixed} Returns the last element(s) of `array`.
+   * @example
+   *
+   * _.last([1, 2, 3]);
+   * // => 3
+   *
+   * _.last([1, 2, 3], 2);
+   * // => [2, 3]
+   *
+   * _.last([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [2, 3]
+   *
+   * var food = [
+   *   { 'name': 'beet',   'organic': false },
+   *   { 'name': 'carrot', 'organic': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.last(food, 'organic');
+   * // => [{ 'name': 'carrot', 'organic': true }]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' },
+   *   { 'name': 'carrot', 'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.last(food, { 'type': 'vegetable' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
+   */
+  function last(array, callback, thisArg) {
+    if (array) {
+      var n = 0,
+          length = array.length;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = createCallback(callback, thisArg);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array[length - 1];
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+  }
+
+  /**
+   * Gets the index at which the last occurrence of `value` is found using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=array.length-1] The index to search from.
+   * @returns {Number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 4
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 1
+   */
+  function lastIndexOf(array, value, fromIndex) {
+    var index = array ? array.length : 0;
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+    }
+    while (index--) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Creates an object composed from arrays of `keys` and `values`. Pass either
+   * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
+   * two arrays, one of `keys` and one of corresponding `values`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} keys The array of keys.
+   * @param {Array} [values=[]] The array of values.
+   * @returns {Object} Returns an object composed of the given keys and
+   *  corresponding values.
+   * @example
+   *
+   * _.object(['moe', 'larry'], [30, 40]);
+   * // => { 'moe': 30, 'larry': 40 }
+   */
+  function object(keys, values) {
+    var index = -1,
+        length = keys ? keys.length : 0,
+        result = {};
+
+    while (++index < length) {
+      var key = keys[index];
+      if (values) {
+        result[key] = values[index];
+      } else {
+        result[key[0]] = key[1];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array of numbers (positive and/or negative) progressing from
+   * `start` up to but not including `end`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Number} [start=0] The start of the range.
+   * @param {Number} end The end of the range.
+   * @param {Number} [step=1] The value to increment or descrement by.
+   * @returns {Array} Returns a new range array.
+   * @example
+   *
+   * _.range(10);
+   * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+   *
+   * _.range(1, 11);
+   * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+   *
+   * _.range(0, 30, 5);
+   * // => [0, 5, 10, 15, 20, 25]
+   *
+   * _.range(0, -10, -1);
+   * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+   *
+   * _.range(0);
+   * // => []
+   */
+  function range(start, end, step) {
+    start = +start || 0;
+    step = +step || 1;
+
+    if (end == null) {
+      end = start;
+      start = 0;
+    }
+    // use `Array(length)` so V8 will avoid the slower "dictionary" mode
+    // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+    var index = -1,
+        length = nativeMax(0, ceil((end - start) / step)),
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = start;
+      start += step;
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.initial`, this method gets all but the first value of `array`.
+   * If a number `n` is passed, the first `n` values are excluded from the result.
+   * If a `callback` function is passed, the first elements the `callback` returns
+   * truthy for are excluded from the result. The `callback` is bound to `thisArg`
+   * and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias drop, tail
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|Number|String} [callback|n=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is passed, it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.rest([1, 2, 3]);
+   * // => [2, 3]
+   *
+   * _.rest([1, 2, 3], 2);
+   * // => [3]
+   *
+   * _.rest([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [3]
+   *
+   * var food = [
+   *   { 'name': 'banana', 'organic': true },
+   *   { 'name': 'beet',   'organic': false },
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.rest(food, 'organic');
+   * // => [{ 'name': 'beet', 'organic': false }]
+   *
+   * var food = [
+   *   { 'name': 'apple',  'type': 'fruit' },
+   *   { 'name': 'banana', 'type': 'fruit' },
+   *   { 'name': 'beet',   'type': 'vegetable' }
+   * ];
+   *
+   * // using "_.where" callback shorthand
+   * _.rest(food, { 'type': 'fruit' });
+   * // => [{ 'name': 'beet', 'type': 'vegetable' }]
+   */
+  function rest(array, callback, thisArg) {
+    if (typeof callback != 'number' && callback != null) {
+      var n = 0,
+          index = -1,
+          length = array ? array.length : 0;
+
+      callback = createCallback(callback, thisArg);
+      while (++index < length && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+    }
+    return slice(array, n);
+  }
+
+  /**
+   * Uses a binary search to determine the smallest index at which the `value`
+   * should be inserted into `array` in order to maintain the sort order of the
+   * sorted `array`. If `callback` is passed, it will be executed for `value` and
+   * each element in `array` to compute their sort ranking. The `callback` is
+   * bound to `thisArg` and invoked with one argument; (value).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to iterate over.
+   * @param {Mixed} value The value to evaluate.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Number} Returns the index at which the value should be inserted
+   *  into `array`.
+   * @example
+   *
+   * _.sortedIndex([20, 30, 50], 40);
+   * // => 2
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+   * // => 2
+   *
+   * var dict = {
+   *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+   * };
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return dict.wordToNumber[word];
+   * });
+   * // => 2
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return this.wordToNumber[word];
+   * }, dict);
+   * // => 2
+   */
+  function sortedIndex(array, value, callback, thisArg) {
+    var low = 0,
+        high = array ? array.length : low;
+
+    // explicitly reference `identity` for better inlining in Firefox
+    callback = callback ? createCallback(callback, thisArg, 1) : identity;
+    value = callback(value);
+
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      callback(array[mid]) < value
+        ? low = mid + 1
+        : high = mid;
+    }
+    return low;
+  }
+
+  /**
+   * Computes the union of the passed-in arrays using strict equality for
+   * comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of unique values, in order, that are
+   *  present in one or more of the arrays.
+   * @example
+   *
+   * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+   * // => [1, 2, 3, 101, 10]
+   */
+  function union() {
+    return uniq(concat.apply(arrayRef, arguments));
+  }
+
+  /**
+   * Creates a duplicate-value-free version of the `array` using strict equality
+   * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
+   * for `isSorted` will run a faster algorithm. If `callback` is passed, each
+   * element of `array` is passed through a callback` before uniqueness is computed.
+   * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is passed for `callback`, the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is passed for `callback`, the created "_.where" style callback
+   * will return `true` for elements that have the propeties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias unique
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+   * @param {Function|Object|String} [callback=identity] The function called per
+   *  iteration. If a property name or object is passed, it will be used to create
+   *  a "_.pluck" or "_.where" style callback, respectively.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a duplicate-value-free array.
+   * @example
+   *
+   * _.uniq([1, 2, 1, 3, 1]);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 1, 2, 2, 3], true);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
+   * // => [1, 2, 3]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+   * // => [{ 'x': 1 }, { 'x': 2 }]
+   */
+  function uniq(array, isSorted, callback, thisArg) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [],
+        seen = result;
+
+    // juggle arguments
+    if (typeof isSorted == 'function') {
+      thisArg = callback;
+      callback = isSorted;
+      isSorted = false;
+    }
+    // init value cache for large arrays
+    var isLarge = !isSorted && length >= 75;
+    if (isLarge) {
+      var cache = {};
+    }
+    if (callback) {
+      seen = [];
+      callback = createCallback(callback, thisArg);
+    }
+    while (++index < length) {
+      var value = array[index],
+          computed = callback ? callback(value, index, array) : value;
+
+      if (isLarge) {
+        var key = computed + '';
+        var inited = hasOwnProperty.call(cache, key)
+          ? !(seen = cache[key])
+          : (seen = cache[key] = []);
+      }
+      if (isSorted
+            ? !index || seen[seen.length - 1] !== computed
+            : inited || indexOf(seen, computed) < 0
+          ) {
+        if (callback || isLarge) {
+          seen.push(computed);
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array with all occurrences of the passed values removed using
+   * strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to filter.
+   * @param {Mixed} [value1, value2, ...] Values to remove.
+   * @returns {Array} Returns a new filtered array.
+   * @example
+   *
+   * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+   * // => [2, 3, 4]
+   */
+  function without(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        contains = cachedContains(arguments, 1),
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (!contains(value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Groups the elements of each array at their corresponding indexes. Useful for
+   * separate data sources that are coordinated through matching array indexes.
+   * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
+   * in a similar fashion.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} [array1, array2, ...] Arrays to process.
+   * @returns {Array} Returns a new array of grouped elements.
+   * @example
+   *
+   * _.zip(['moe', 'larry'], [30, 40], [true, false]);
+   * // => [['moe', 30, true], ['larry', 40, false]]
+   */
+  function zip(array) {
+    var index = -1,
+        length = array ? max(pluck(arguments, 'length')) : 0,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = pluck(arguments, index);
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function that is restricted to executing `func` only after it is
+   * called `n` times. The `func` is executed with the `this` binding of the
+   * created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Number} n The number of times the function must be called before
+   * it is executed.
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var renderNotes = _.after(notes.length, render);
+   * _.forEach(notes, function(note) {
+   *   note.asyncSave({ 'success': renderNotes });
+   * });
+   * // `renderNotes` is run once, after all notes have saved
+   */
+  function after(n, func) {
+    if (n < 1) {
+      return func();
+    }
+    return function() {
+      if (--n < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this`
+   * binding of `thisArg` and prepends any additional `bind` arguments to those
+   * passed to the bound function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to bind.
+   * @param {Mixed} [thisArg] The `this` binding of `func`.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var func = function(greeting) {
+   *   return greeting + ' ' + this.name;
+   * };
+   *
+   * func = _.bind(func, { 'name': 'moe' }, 'hi');
+   * func();
+   * // => 'hi moe'
+   */
+  function bind(func, thisArg) {
+    // use `Function#bind` if it exists and is fast
+    // (in V8 `Function#bind` is slower except when partially applied)
+    return isBindFast || (nativeBind && arguments.length > 2)
+      ? nativeBind.call.apply(nativeBind, arguments)
+      : createBound(func, thisArg, slice(arguments, 2));
+  }
+
+  /**
+   * Binds methods on `object` to `object`, overwriting the existing method.
+   * Method names may be specified as individual arguments or as arrays of method
+   * names. If no method names are provided, all the function properties of `object`
+   * will be bound.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object to bind and assign the bound methods to.
+   * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * var view = {
+   *  'label': 'docs',
+   *  'onClick': function() { alert('clicked ' + this.label); }
+   * };
+   *
+   * _.bindAll(view);
+   * jQuery('#docs').on('click', view.onClick);
+   * // => alerts 'clicked docs', when the button is clicked
+   */
+  function bindAll(object) {
+    var funcs = concat.apply(arrayRef, arguments),
+        index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
+        length = funcs.length;
+
+    while (++index < length) {
+      var key = funcs[index];
+      object[key] = bind(object[key], object);
+    }
+    return object;
+  }
+
+  /**
+   * Creates a function that, when called, invokes the method at `object[key]`
+   * and prepends any additional `bindKey` arguments to those passed to the bound
+   * function. This method differs from `_.bind` by allowing bound functions to
+   * reference methods that will be redefined or don't yet exist.
+   * See http://michaux.ca/articles/lazy-function-definition-pattern.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object the method belongs to.
+   * @param {String} key The key of the method.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var object = {
+   *   'name': 'moe',
+   *   'greet': function(greeting) {
+   *     return greeting + ' ' + this.name;
+   *   }
+   * };
+   *
+   * var func = _.bindKey(object, 'greet', 'hi');
+   * func();
+   * // => 'hi moe'
+   *
+   * object.greet = function(greeting) {
+   *   return greeting + ', ' + this.name + '!';
+   * };
+   *
+   * func();
+   * // => 'hi, moe!'
+   */
+  function bindKey(object, key) {
+    return createBound(object, key, slice(arguments, 2));
+  }
+
+  /**
+   * Creates a function that is the composition of the passed functions,
+   * where each function consumes the return value of the function that follows.
+   * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+   * Each function is executed with the `this` binding of the composed function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} [func1, func2, ...] Functions to compose.
+   * @returns {Function} Returns the new composed function.
+   * @example
+   *
+   * var greet = function(name) { return 'hi ' + name; };
+   * var exclaim = function(statement) { return statement + '!'; };
+   * var welcome = _.compose(exclaim, greet);
+   * welcome('moe');
+   * // => 'hi moe!'
+   */
+  function compose() {
+    var funcs = arguments;
+    return function() {
+      var args = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        args = [funcs[length].apply(this, args)];
+      }
+      return args[0];
+    };
+  }
+
+  /**
+   * Creates a function that will delay the execution of `func` until after
+   * `wait` milliseconds have elapsed since the last time it was invoked. Pass
+   * `true` for `immediate` to cause debounce to invoke `func` on the leading,
+   * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
+   * the debounced function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to debounce.
+   * @param {Number} wait The number of milliseconds to delay.
+   * @param {Boolean} immediate A flag to indicate execution is on the leading
+   *  edge of the timeout.
+   * @returns {Function} Returns the new debounced function.
+   * @example
+   *
+   * var lazyLayout = _.debounce(calculateLayout, 300);
+   * jQuery(window).on('resize', lazyLayout);
+   */
+  function debounce(func, wait, immediate) {
+    var args,
+        result,
+        thisArg,
+        timeoutId;
+
+    function delayed() {
+      timeoutId = null;
+      if (!immediate) {
+        result = func.apply(thisArg, args);
+      }
+    }
+    return function() {
+      var isImmediate = immediate && !timeoutId;
+      args = arguments;
+      thisArg = this;
+
+      clearTimeout(timeoutId);
+      timeoutId = setTimeout(delayed, wait);
+
+      if (isImmediate) {
+        result = func.apply(thisArg, args);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Executes the `func` function after `wait` milliseconds. Additional arguments
+   * will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to delay.
+   * @param {Number} wait The number of milliseconds to delay execution.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * var log = _.bind(console.log, console);
+   * _.delay(log, 1000, 'logged later');
+   * // => 'logged later' (Appears after one second.)
+   */
+  function delay(func, wait) {
+    var args = slice(arguments, 2);
+    return setTimeout(function() { func.apply(undefined, args); }, wait);
+  }
+
+  /**
+   * Defers executing the `func` function until the current call stack has cleared.
+   * Additional arguments will be passed to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to defer.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+   * @returns {Number} Returns the `setTimeout` timeout id.
+   * @example
+   *
+   * _.defer(function() { alert('deferred'); });
+   * // returns from the function before `alert` is called
+   */
+  function defer(func) {
+    var args = slice(arguments, 1);
+    return setTimeout(function() { func.apply(undefined, args); }, 1);
+  }
+  // use `setImmediate` if it's available in Node.js
+  if (isV8 && freeModule && typeof setImmediate == 'function') {
+    defer = bind(setImmediate, window);
+  }
+
+  /**
+   * Creates a function that memoizes the result of `func`. If `resolver` is
+   * passed, it will be used to determine the cache key for storing the result
+   * based on the arguments passed to the memoized function. By default, the first
+   * argument passed to the memoized function is used as the cache key. The `func`
+   * is executed with the `this` binding of the memoized function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to have its output memoized.
+   * @param {Function} [resolver] A function used to resolve the cache key.
+   * @returns {Function} Returns the new memoizing function.
+   * @example
+   *
+   * var fibonacci = _.memoize(function(n) {
+   *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+   * });
+   */
+  function memoize(func, resolver) {
+    var cache = {};
+    return function() {
+      var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
+      return hasOwnProperty.call(cache, key)
+        ? cache[key]
+        : (cache[key] = func.apply(this, arguments));
+    };
+  }
+
+  /**
+   * Creates a function that is restricted to execute `func` once. Repeat calls to
+   * the function will return the value of the first call. The `func` is executed
+   * with the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var initialize = _.once(createApplication);
+   * initialize();
+   * initialize();
+   * // `initialize` executes `createApplication` once
+   */
+  function once(func) {
+    var ran,
+        result;
+
+    return function() {
+      if (ran) {
+        return result;
+      }
+      ran = true;
+      result = func.apply(this, arguments);
+
+      // clear the `func` variable so the function may be garbage collected
+      func = null;
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with any additional
+   * `partial` arguments prepended to those passed to the new function. This
+   * method is similar to `_.bind`, except it does **not** alter the `this` binding.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var greet = function(greeting, name) { return greeting + ' ' + name; };
+   * var hi = _.partial(greet, 'hi');
+   * hi('moe');
+   * // => 'hi moe'
+   */
+  function partial(func) {
+    return createBound(func, slice(arguments, 1));
+  }
+
+  /**
+   * This method is similar to `_.partial`, except that `partial` arguments are
+   * appended to those passed to the new function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var defaultsDeep = _.partialRight(_.merge, _.defaults);
+   *
+   * var options = {
+   *   'variable': 'data',
+   *   'imports': { 'jq': $ }
+   * };
+   *
+   * defaultsDeep(options, _.templateSettings);
+   *
+   * options.variable
+   * // => 'data'
+   *
+   * options.imports
+   * // => { '_': _, 'jq': $ }
+   */
+  function partialRight(func) {
+    return createBound(func, slice(arguments, 1), null, indicatorObject);
+  }
+
+  /**
+   * Creates a function that, when executed, will only call the `func`
+   * function at most once per every `wait` milliseconds. If the throttled
+   * function is invoked more than once during the `wait` timeout, `func` will
+   * also be called on the trailing edge of the timeout. Subsequent calls to the
+   * throttled function will return the result of the last `func` call.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to throttle.
+   * @param {Number} wait The number of milliseconds to throttle executions to.
+   * @returns {Function} Returns the new throttled function.
+   * @example
+   *
+   * var throttled = _.throttle(updatePosition, 100);
+   * jQuery(window).on('scroll', throttled);
+   */
+  function throttle(func, wait) {
+    var args,
+        result,
+        thisArg,
+        timeoutId,
+        lastCalled = 0;
+
+    function trailingCall() {
+      lastCalled = new Date;
+      timeoutId = null;
+      result = func.apply(thisArg, args);
+    }
+    return function() {
+      var now = new Date,
+          remaining = wait - (now - lastCalled);
+
+      args = arguments;
+      thisArg = this;
+
+      if (remaining <= 0) {
+        clearTimeout(timeoutId);
+        timeoutId = null;
+        lastCalled = now;
+        result = func.apply(thisArg, args);
+      }
+      else if (!timeoutId) {
+        timeoutId = setTimeout(trailingCall, remaining);
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that passes `value` to the `wrapper` function as its
+   * first argument. Additional arguments passed to the function are appended
+   * to those passed to the `wrapper` function. The `wrapper` is executed with
+   * the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Mixed} value The value to wrap.
+   * @param {Function} wrapper The wrapper function.
+   * @returns {Function} Returns the new function.
+   * @example
+   *
+   * var hello = function(name) { return 'hello ' + name; };
+   * hello = _.wrap(hello, function(func) {
+   *   return 'before, ' + func('moe') + ', after';
+   * });
+   * hello();
+   * // => 'before, hello moe, after'
+   */
+  function wrap(value, wrapper) {
+    return function() {
+      var args = [value];
+      push.apply(args, arguments);
+      return wrapper.apply(this, args);
+    };
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+   * corresponding HTML entities.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to escape.
+   * @returns {String} Returns the escaped string.
+   * @example
+   *
+   * _.escape('Moe, Larry & Curly');
+   * // => 'Moe, Larry &amp; Curly'
+   */
+  function escape(string) {
+    return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
+  }
+
+  /**
+   * This function returns the first argument passed to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Mixed} value Any value.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * var moe = { 'name': 'moe' };
+   * moe === _.identity(moe);
+   * // => true
+   */
+  function identity(value) {
+    return value;
+  }
+
+  /**
+   * Adds functions properties of `object` to the `lodash` function and chainable
+   * wrapper.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object of function properties to add to `lodash`.
+   * @example
+   *
+   * _.mixin({
+   *   'capitalize': function(string) {
+   *     return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+   *   }
+   * });
+   *
+   * _.capitalize('moe');
+   * // => 'Moe'
+   *
+   * _('moe').capitalize();
+   * // => 'Moe'
+   */
+  function mixin(object) {
+    forEach(functions(object), function(methodName) {
+      var func = lodash[methodName] = object[methodName];
+
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        return new lodash(func.apply(lodash, args));
+      };
+    });
+  }
+
+  /**
+   * Reverts the '_' variable to its previous value and returns a reference to
+   * the `lodash` function.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @returns {Function} Returns the `lodash` function.
+   * @example
+   *
+   * var lodash = _.noConflict();
+   */
+  function noConflict() {
+    window._ = oldDash;
+    return this;
+  }
+
+  /**
+   * Produces a random number between `min` and `max` (inclusive). If only one
+   * argument is passed, a number between `0` and the given number will be returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} [min=0] The minimum possible value.
+   * @param {Number} [max=1] The maximum possible value.
+   * @returns {Number} Returns a random number.
+   * @example
+   *
+   * _.random(0, 5);
+   * // => a number between 0 and 5
+   *
+   * _.random(5);
+   * // => also a number between 0 and 5
+   */
+  function random(min, max) {
+    if (min == null && max == null) {
+      max = 1;
+    }
+    min = +min || 0;
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + floor(nativeRandom() * ((+max || 0) - min + 1));
+  }
+
+  /**
+   * Resolves the value of `property` on `object`. If `property` is a function,
+   * it will be invoked and its result returned, else the property value is
+   * returned. If `object` is falsey, then `null` is returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object to inspect.
+   * @param {String} property The property to get the value of.
+   * @returns {Mixed} Returns the resolved value.
+   * @example
+   *
+   * var object = {
+   *   'cheese': 'crumpets',
+   *   'stuff': function() {
+   *     return 'nonsense';
+   *   }
+   * };
+   *
+   * _.result(object, 'cheese');
+   * // => 'crumpets'
+   *
+   * _.result(object, 'stuff');
+   * // => 'nonsense'
+   */
+  function result(object, property) {
+    var value = object ? object[property] : undefined;
+    return isFunction(value) ? object[property]() : value;
+  }
+
+  /**
+   * A micro-templating method that handles arbitrary delimiters, preserves
+   * whitespace, and correctly escapes quotes within interpolated code.
+   *
+   * Note: In the development build, `_.template` utilizes sourceURLs for easier
+   * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+   *
+   * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
+   * build and using precompiled templates, or loading Lo-Dash in a sandbox.
+   *
+   * For more information on precompiling templates see:
+   * http://lodash.com/#custom-builds
+   *
+   * For more information on Chrome extension sandboxes see:
+   * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} text The template text.
+   * @param {Obect} data The data object used to populate the text.
+   * @param {Object} options The options object.
+   *  escape - The "escape" delimiter regexp.
+   *  evaluate - The "evaluate" delimiter regexp.
+   *  interpolate - The "interpolate" delimiter regexp.
+   *  sourceURL - The sourceURL of the template's compiled source.
+   *  variable - The data object variable name.
+   *
+   * @returns {Function|String} Returns a compiled function when no `data` object
+   *  is given, else it returns the interpolated text.
+   * @example
+   *
+   * // using a compiled template
+   * var compiled = _.template('hello <%= name %>');
+   * compiled({ 'name': 'moe' });
+   * // => 'hello moe'
+   *
+   * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
+   * _.template(list, { 'people': ['moe', 'larry'] });
+   * // => '<li>moe</li><li>larry</li>'
+   *
+   * // using the "escape" delimiter to escape HTML in data property values
+   * _.template('<b><%- value %></b>', { 'value': '<script>' });
+   * // => '<b>&lt;script&gt;</b>'
+   *
+   * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+   * _.template('hello ${ name }', { 'name': 'curly' });
+   * // => 'hello curly'
+   *
+   * // using the internal `print` function in "evaluate" delimiters
+   * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
+   * // => 'hello stooge!'
+   *
+   * // using custom template delimiters
+   * _.templateSettings = {
+   *   'interpolate': /{{([\s\S]+?)}}/g
+   * };
+   *
+   * _.template('hello {{ name }}!', { 'name': 'mustache' });
+   * // => 'hello mustache!'
+   *
+   * // using the `sourceURL` option to specify a custom sourceURL for the template
+   * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+   * compiled(data);
+   * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+   *
+   * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+   * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+   * compiled.source;
+   * // => function(data) {
+   *   var __t, __p = '', __e = _.escape;
+   *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+   *   return __p;
+   * }
+   *
+   * // using the `source` property to inline compiled templates for meaningful
+   * // line numbers in error messages and a stack trace
+   * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+   *   var JST = {\
+   *     "main": ' + _.template(mainText).source + '\
+   *   };\
+   * ');
+   */
+  function template(text, data, options) {
+    // based on John Resig's `tmpl` implementation
+    // http://ejohn.org/blog/javascript-micro-templating/
+    // and Laura Doktorova's doT.js
+    // https://github.com/olado/doT
+    var settings = lodash.templateSettings;
+    text || (text = '');
+
+    // avoid missing dependencies when `iteratorTemplate` is not defined
+    options = iteratorTemplate ? defaults({}, options, settings) : settings;
+
+    var imports = iteratorTemplate && defaults({}, options.imports, settings.imports),
+        importsKeys = iteratorTemplate ? keys(imports) : ['_'],
+        importsValues = iteratorTemplate ? values(imports) : [lodash];
+
+    var isEvaluating,
+        index = 0,
+        interpolate = options.interpolate || reNoMatch,
+        source = "__p += '";
+
+    // compile regexp to match each delimiter
+    var reDelimiters = RegExp(
+      (options.escape || reNoMatch).source + '|' +
+      interpolate.source + '|' +
+      (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+      (options.evaluate || reNoMatch).source + '|$'
+    , 'g');
+
+    text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+      interpolateValue || (interpolateValue = esTemplateValue);
+
+      // escape characters that cannot be included in string literals
+      source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+      // replace delimiters with snippets
+      if (escapeValue) {
+        source += "' +\n__e(" + escapeValue + ") +\n'";
+      }
+      if (evaluateValue) {
+        isEvaluating = true;
+        source += "';\n" + evaluateValue + ";\n__p += '";
+      }
+      if (interpolateValue) {
+        source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+      }
+      index = offset + match.length;
+
+      // the JS engine embedded in Adobe products requires returning the `match`
+      // string in order to produce the correct `offset` value
+      return match;
+    });
+
+    source += "';\n";
+
+    // if `variable` is not specified and the template contains "evaluate"
+    // delimiters, wrap a with-statement around the generated code to add the
+    // data object to the top of the scope chain
+    var variable = options.variable,
+        hasVariable = variable;
+
+    if (!hasVariable) {
+      variable = 'obj';
+      source = 'with (' + variable + ') {\n' + source + '\n}\n';
+    }
+    // cleanup code by stripping empty strings
+    source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+      .replace(reEmptyStringMiddle, '$1')
+      .replace(reEmptyStringTrailing, '$1;');
+
+    // frame code as the function body
+    source = 'function(' + variable + ') {\n' +
+      (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+      "var __t, __p = '', __e = _.escape" +
+      (isEvaluating
+        ? ', __j = Array.prototype.join;\n' +
+          "function print() { __p += __j.call(arguments, '') }\n"
+        : ';\n'
+      ) +
+      source +
+      'return __p\n}';
+
+    // Use a sourceURL for easier debugging and wrap in a multi-line comment to
+    // avoid issues with Narwhal, IE conditional compilation, and the JS engine
+    // embedded in Adobe products.
+    // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+    var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
+
+    try {
+      var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
+    } catch(e) {
+      e.source = source;
+      throw e;
+    }
+    if (data) {
+      return result(data);
+    }
+    // provide the compiled function's source via its `toString` method, in
+    // supported environments, or the `source` property as a convenience for
+    // inlining compiled templates during the build process
+    result.source = source;
+    return result;
+  }
+
+  /**
+   * Executes the `callback` function `n` times, returning an array of the results
+   * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
+   * with one argument; (index).
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Number} n The number of times to execute the callback.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+   * // => [3, 6, 4]
+   *
+   * _.times(3, function(n) { mage.castSpell(n); });
+   * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+   *
+   * _.times(3, function(n) { this.cast(n); }, mage);
+   * // => also calls `mage.castSpell(n)` three times
+   */
+  function times(n, callback, thisArg) {
+    n = +n || 0;
+    var index = -1,
+        result = Array(n);
+
+    while (++index < n) {
+      result[index] = callback.call(thisArg, index);
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.escape`, this method converts the HTML entities
+   * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+   * corresponding characters.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} string The string to unescape.
+   * @returns {String} Returns the unescaped string.
+   * @example
+   *
+   * _.unescape('Moe, Larry &amp; Curly');
+   * // => 'Moe, Larry & Curly'
+   */
+  function unescape(string) {
+    return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
+  }
+
+  /**
+   * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {String} [prefix] The value to prefix the ID with.
+   * @returns {String} Returns the unique ID.
+   * @example
+   *
+   * _.uniqueId('contact_');
+   * // => 'contact_104'
+   *
+   * _.uniqueId();
+   * // => '105'
+   */
+  function uniqueId(prefix) {
+    var id = ++idCounter;
+    return (prefix == null ? '' : prefix + '') + id;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Invokes `interceptor` with the `value` as the first argument, and then
+   * returns `value`. The purpose of this method is to "tap into" a method chain,
+   * in order to perform operations on intermediate results within the chain.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {Mixed} value The value to pass to `interceptor`.
+   * @param {Function} interceptor The function to invoke.
+   * @returns {Mixed} Returns `value`.
+   * @example
+   *
+   * _([1, 2, 3, 4])
+   *  .filter(function(num) { return num % 2 == 0; })
+   *  .tap(alert)
+   *  .map(function(num) { return num * num; })
+   *  .value();
+   * // => // [2, 4] (alerted)
+   * // => [4, 16]
+   */
+  function tap(value, interceptor) {
+    interceptor(value);
+    return value;
+  }
+
+  /**
+   * Produces the `toString` result of the wrapped value.
+   *
+   * @name toString
+   * @memberOf _
+   * @category Chaining
+   * @returns {String} Returns the string result.
+   * @example
+   *
+   * _([1, 2, 3]).toString();
+   * // => '1,2,3'
+   */
+  function wrapperToString() {
+    return this.__wrapped__ + '';
+  }
+
+  /**
+   * Extracts the wrapped value.
+   *
+   * @name valueOf
+   * @memberOf _
+   * @alias value
+   * @category Chaining
+   * @returns {Mixed} Returns the wrapped value.
+   * @example
+   *
+   * _([1, 2, 3]).valueOf();
+   * // => [1, 2, 3]
+   */
+  function wrapperValueOf() {
+    return this.__wrapped__;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return wrapped values when chaining
+  lodash.after = after;
+  lodash.assign = assign;
+  lodash.at = at;
+  lodash.bind = bind;
+  lodash.bindAll = bindAll;
+  lodash.bindKey = bindKey;
+  lodash.compact = compact;
+  lodash.compose = compose;
+  lodash.countBy = countBy;
+  lodash.debounce = debounce;
+  lodash.defaults = defaults;
+  lodash.defer = defer;
+  lodash.delay = delay;
+  lodash.difference = difference;
+  lodash.filter = filter;
+  lodash.flatten = flatten;
+  lodash.forEach = forEach;
+  lodash.forIn = forIn;
+  lodash.forOwn = forOwn;
+  lodash.functions = functions;
+  lodash.groupBy = groupBy;
+  lodash.initial = initial;
+  lodash.intersection = intersection;
+  lodash.invert = invert;
+  lodash.invoke = invoke;
+  lodash.keys = keys;
+  lodash.map = map;
+  lodash.max = max;
+  lodash.memoize = memoize;
+  lodash.merge = merge;
+  lodash.min = min;
+  lodash.object = object;
+  lodash.omit = omit;
+  lodash.once = once;
+  lodash.pairs = pairs;
+  lodash.partial = partial;
+  lodash.partialRight = partialRight;
+  lodash.pick = pick;
+  lodash.pluck = pluck;
+  lodash.range = range;
+  lodash.reject = reject;
+  lodash.rest = rest;
+  lodash.shuffle = shuffle;
+  lodash.sortBy = sortBy;
+  lodash.tap = tap;
+  lodash.throttle = throttle;
+  lodash.times = times;
+  lodash.toArray = toArray;
+  lodash.union = union;
+  lodash.uniq = uniq;
+  lodash.values = values;
+  lodash.where = where;
+  lodash.without = without;
+  lodash.wrap = wrap;
+  lodash.zip = zip;
+
+  // add aliases
+  lodash.collect = map;
+  lodash.drop = rest;
+  lodash.each = forEach;
+  lodash.extend = assign;
+  lodash.methods = functions;
+  lodash.select = filter;
+  lodash.tail = rest;
+  lodash.unique = uniq;
+
+  // add functions to `lodash.prototype`
+  mixin(lodash);
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return unwrapped values when chaining
+  lodash.clone = clone;
+  lodash.cloneDeep = cloneDeep;
+  lodash.contains = contains;
+  lodash.escape = escape;
+  lodash.every = every;
+  lodash.find = find;
+  lodash.has = has;
+  lodash.identity = identity;
+  lodash.indexOf = indexOf;
+  lodash.isArguments = isArguments;
+  lodash.isArray = isArray;
+  lodash.isBoolean = isBoolean;
+  lodash.isDate = isDate;
+  lodash.isElement = isElement;
+  lodash.isEmpty = isEmpty;
+  lodash.isEqual = isEqual;
+  lodash.isFinite = isFinite;
+  lodash.isFunction = isFunction;
+  lodash.isNaN = isNaN;
+  lodash.isNull = isNull;
+  lodash.isNumber = isNumber;
+  lodash.isObject = isObject;
+  lodash.isPlainObject = isPlainObject;
+  lodash.isRegExp = isRegExp;
+  lodash.isString = isString;
+  lodash.isUndefined = isUndefined;
+  lodash.lastIndexOf = lastIndexOf;
+  lodash.mixin = mixin;
+  lodash.noConflict = noConflict;
+  lodash.random = random;
+  lodash.reduce = reduce;
+  lodash.reduceRight = reduceRight;
+  lodash.result = result;
+  lodash.size = size;
+  lodash.some = some;
+  lodash.sortedIndex = sortedIndex;
+  lodash.template = template;
+  lodash.unescape = unescape;
+  lodash.uniqueId = uniqueId;
+
+  // add aliases
+  lodash.all = every;
+  lodash.any = some;
+  lodash.detect = find;
+  lodash.foldl = reduce;
+  lodash.foldr = reduceRight;
+  lodash.include = contains;
+  lodash.inject = reduce;
+
+  forOwn(lodash, function(func, methodName) {
+    if (!lodash.prototype[methodName]) {
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+        return func.apply(lodash, args);
+      };
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions capable of returning wrapped and unwrapped values when chaining
+  lodash.first = first;
+  lodash.last = last;
+
+  // add aliases
+  lodash.take = first;
+  lodash.head = first;
+
+  forOwn(lodash, function(func, methodName) {
+    if (!lodash.prototype[methodName]) {
+      lodash.prototype[methodName]= function(callback, thisArg) {
+        var result = func(this.__wrapped__, callback, thisArg);
+        return callback == null || (thisArg && typeof callback != 'function')
+          ? result
+          : new lodash(result);
+      };
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The semantic version number.
+   *
+   * @static
+   * @memberOf _
+   * @type String
+   */
+  lodash.VERSION = '1.0.1';
+
+  // add "Chaining" functions to the wrapper
+  lodash.prototype.toString = wrapperToString;
+  lodash.prototype.value = wrapperValueOf;
+  lodash.prototype.valueOf = wrapperValueOf;
+
+  // add `Array` functions that return unwrapped values
+  each(['join', 'pop', 'shift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      return func.apply(this.__wrapped__, arguments);
+    };
+  });
+
+  // add `Array` functions that return the wrapped value
+  each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      func.apply(this.__wrapped__, arguments);
+      return this;
+    };
+  });
+
+  // add `Array` functions that return new wrapped values
+  each(['concat', 'slice', 'splice'], function(methodName) {
+    var func = arrayRef[methodName];
+    lodash.prototype[methodName] = function() {
+      return new lodash(func.apply(this.__wrapped__, arguments));
+    };
+  });
+
+  // avoid array-like object bugs with `Array#shift` and `Array#splice`
+  // in Firefox < 10 and IE < 9
+  if (hasObjectSpliceBug) {
+    each(['pop', 'shift', 'splice'], function(methodName) {
+      var func = arrayRef[methodName],
+          isSplice = methodName == 'splice';
+
+      lodash.prototype[methodName] = function() {
+        var value = this.__wrapped__,
+            result = func.apply(value, arguments);
+
+        if (value.length === 0) {
+          delete value[0];
+        }
+        return isSplice ? new lodash(result) : result;
+      };
+    });
+  }
+
+  // add pseudo private property to be used and removed during the build process
+  lodash._each = each;
+  lodash._iteratorTemplate = iteratorTemplate;
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Lo-Dash
+  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash was injected by a third-party script and not intended to be
+    // loaded as a module. The global assignment can be reverted in the Lo-Dash
+    // module via its `noConflict()` method.
+    window._ = lodash;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return lodash;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports) {
+    // in Node.js or RingoJS v0.8.0+
+    if (freeModule) {
+      (freeModule.exports = lodash)._ = lodash;
+    }
+    // in Narwhal or RingoJS v0.7.0-
+    else {
+      freeExports._ = lodash;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    window._ = lodash;
+  }
+}(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/package.json	(revision 533)
@@ -0,0 +1,56 @@
+{
+  "name": "lodash",
+  "version": "1.0.1",
+  "description": "An alternative to Underscore.js, delivering consistency, customization, performance, and extra features.",
+  "homepage": "http://lodash.com",
+  "main": "./dist/lodash",
+  "keywords": [
+    "browser",
+    "client",
+    "functional",
+    "performance",
+    "server",
+    "speed",
+    "util"
+  ],
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://lodash.com/license"
+    }
+  ],
+  "author": {
+    "name": "John-David Dalton",
+    "email": "john.david.dalton@gmail.com",
+    "url": "http://allyoucanleet.com/"
+  },
+  "bugs": {
+    "url": "https://github.com/bestiejs/lodash/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/bestiejs/lodash.git"
+  },
+  "bin": {
+    "lodash": "./build.js"
+  },
+  "directories": {
+    "doc": "./doc",
+    "test": "./test"
+  },
+  "engines": [
+    "node",
+    "rhino"
+  ],
+  "jam": {
+    "main": "./lodash.js"
+  },
+  "scripts": {
+    "build": "node ./build.js",
+    "test": "node ./test/test.js ./dist/lodash.js && node ./test/test.js ./dist/lodash.min.js && node ./test/test-build.js"
+  },
+  "readme": "# Lo-Dash <sup>v1.0.1</sup>\n[![build status](https://secure.travis-ci.org/bestiejs/lodash.png)](http://travis-ci.org/bestiejs/lodash)\n\nAn alternative to Underscore.js, delivering consistency, [customization](https://github.com/bestiejs/lodash#custom-builds), [performance](http://lodash.com/benchmarks), and [extra features](https://github.com/bestiejs/lodash#features).\n\n## Download\n\n* Lo-Dash builds (for modern environments):<br>\n[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.js) and\n[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.min.js)\n\n* Lo-Dash compatibility builds (for legacy and modern environments):<br>\n[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.compat.js) and\n[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.compat.min.js)\n\n* Underscore compatibility builds:<br>\n[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.underscore.js) and\n[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.underscore.min.js)\n\n* CDN copies of â€ v1.0.1âs builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/):<br>\n[Lo-Dash dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.js),\n[Lo-Dash prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.min.js),<br>\n[Lo-Dash compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.js),\n[Lo-Dash compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.min.js),<br>\n[Underscore compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.js), and\n[Underscore compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.min.js)\n\n* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need\n\n## Dive in\n\nWeâve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).\n\nFor a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).\n\n## Resources\n\nFor more information check out these articles, screencasts, and other videos over Lo-Dash:\n\n * Posts\n  - [Say âHelloâ to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)\n\n * Videos\n  - [Introducing Lo-Dash](https://vimeo.com/44154599)\n  - [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)\n  - [Lo-Dashâs origin and why itâs a better utility belt](https://vimeo.com/44154600)\n  - [Unit testing in Lo-Dash](https://vimeo.com/45865290)\n  - [Lo-Dashâs approach to native method use](https://vimeo.com/48576012)\n  - [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)\n\n## Features\n\n * AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)\n * [_(âŠ)](http://lodash.com/docs#_) supports intuitive chaining\n * [_.at](http://lodash.com/docs#at) for cherry-picking collection values\n * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*âlazyâ* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods\n * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects\n * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument\n * [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early\n * [_.forIn](http://lodash.com/docs#forIn) for iterating over an objectâs own and inherited properties\n * [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objectâs own properties\n * [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor\n * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)\n * [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding\n * [_.template](http://lodash.com/docs#template) supports [*âimportsâ* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)\n * [_.where](http://lodash.com/docs#where) supports deep object comparisons\n * [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick),\n   [and moreâŠ](http://lodash.com/docs \"_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest\") accept `callback` and `thisArg` arguments\n * [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),\n   [and moreâŠ](http://lodash.com/docs \"_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where\") accept strings\n * [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map),\n   [and moreâŠ](http://lodash.com/docs \"_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq\") support *â_.pluckâ* and *â_.whereâ* `callback` shorthands\n\n## Support\n\nLo-Dash has been tested in at least Chrome 5~24, Firefox 1~18, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.20, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.\n\n## Custom builds\n\nCustom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.\nTo top it off, we handle all method dependency and alias mapping for you.\n\n * Backbone builds, with only methods required by Backbone, may be created using the `backbone` modifier argument.\n```bash\nlodash backbone\n```\n\n * CSP builds, supporting default [Content Security Policy](https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html) restrictions, may be created using the `csp` modifier argument.\n   The `csp` modifier is an alais of the `mobile` modifier. Lo-Dash may be used in Chrome extensions by using either the `csp`, `mobile`, or `underscore` build and using precompiled templates, or loading Lo-Dash in a [sandbox](http://developer.chrome.com/stable/extensions/sandboxingEval.html).\n```bash\nlodash csp\n```\n\n * Legacy builds, tailored for older environments without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.\n```bash\nlodash legacy\n```\n\n * Modern builds, tailored for newer environments with ES5 support, may be created using the `modern` modifier argument.\n```bash\nlodash modern\n```\n\n * Mobile builds, without method compilation and most bug fixes for old browsers, may be created using the `mobile` modifier argument.\n```bash\nlodash mobile\n```\n\n * Strict builds, with `_.bindAll`, `_.defaults`, and `_.extend` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.\n```bash\nlodash strict\n```\n\n * Underscore builds, tailored for projects already using Underscore, may be created using the `underscore` modifier argument.\n```bash\nlodash underscore\n```\n\nCustom builds may be created using the following commands:\n\n * Use the `category` argument to pass comma separated categories of methods to include in the build.<br>\n   Valid categories (case-insensitive) are *âarraysâ*, *âchainingâ*, *âcollectionsâ*, *âfunctionsâ*, *âobjectsâ*, and *âutilitiesâ*.\n```bash\nlodash category=collections,functions\nlodash category=\"collections, functions\"\n```\n\n * Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.<br>\n   Valid exports are *âamdâ*, *âcommonjsâ*, *âglobalâ*, *ânodeâ*, and *ânoneâ*.\n```bash\nlodash exports=amd,commonjs,node\nlodash exports=\"amd, commonjs, node\"\n```\n\n * Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.\n```bash\nlodash iife=\"!function(window,undefined){%output%}(this)\"\n```\n\n * Use the `include` argument to pass comma separated method/category names to include in the build.\n```bash\nlodash include=each,filter,map\nlodash include=\"each, filter, map\"\n```\n\n * Use the `minus` argument to pass comma separated method/category names to remove from those included in the build.\n```bash\nlodash underscore minus=result,shuffle\nlodash underscore minus=\"result, shuffle\"\n```\n\n * Use the `plus` argument to pass comma separated method/category names to add to those included in the build.\n```bash\nlodash backbone plus=random,template\nlodash backbone plus=\"random, template\"\n```\n\n * Use the `template` argument to pass the file path pattern used to match template files to precompile.\n```bash\nlodash template=\"./*.jst\"\n```\n\n * Use the `settings` argument to pass the template settings used when precompiling templates.\n```bash\nlodash settings=\"{interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/g}\"\n```\n\n * Use the `moduleId` argument to specify the AMD module ID of Lo-Dash, which defaults to âlodashâ, used by precompiled templates.\n```bash\nlodash moduleId=\"underscore\"\n```\n\nAll arguments, except `legacy` with `csp`, `mobile`, `modern`, or `underscore`, may be combined.<br>\nUnless specified by `-o` or `--output`, all files created are saved to the current working directory.\n\nThe following options are also supported:\n\n * `-c`, `--stdout` ......... Write output to standard output\n * `-d`, `--debug` ........... Write only the non-minified development output\n * `-h`, `--help` ............. Display help information\n * `-m`, `--minify` ......... Write only the minified production output\n * `-o`, `--output` ......... Write output to a given path/filename\n * `-p`, `--source-map` .. Generate a source map for the minified output, using an optional source map URL\n * `-s`, `--silent` ......... Skip status updates normally logged to the console\n * `-V`, `--version` ....... Output current version of Lo-Dash\n\nThe `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).\n\n## Installation and usage\n\nIn browsers:\n\n```html\n<script src=\"lodash.js\"></script>\n```\n\nUsing [`npm`](http://npmjs.org/):\n\n```bash\nnpm install lodash\n\nnpm install -g lodash\nnpm link lodash\n```\n\nTo avoid potential issues, update `npm` before installing Lo-Dash:\n\n```bash\nnpm install npm -g\n```\n\nIn [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):\n\n```js\nvar _ = require('lodash');\n\n// or as a drop-in replacement for Underscore\nvar _ = require('lodash/lodash.underscore');\n```\n\n**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projectâs root directory before requiring it.\n\nIn [RingoJS v0.7.0-](http://ringojs.org/):\n\n```js\nvar _ = require('lodash')._;\n```\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('lodash.js');\n```\n\nIn an AMD loader like [RequireJS](http://requirejs.org/):\n\n```js\nrequire({\n  'paths': {\n    'underscore': 'path/to/lodash'\n  }\n},\n['underscore'], function(_) {\n  console.log(_.VERSION);\n});\n```\n\n## Release Notes\n\n### <sup>v1.0.1</sup>\n\n * Add support for specifying source map URLs in `-p`/`--source-map` build options\n * Ensured the second argument passed to `_.assign` is not treated as a `callback`\n * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL`\n * Made `-p`/`--source-map` build options set source map *âsourcesâ* keys based on the builds performed\n * Made `_.defer` use `setImmediate`, in Node.js, when available\n * Made `_.where` search arrays for values regardless of their index position\n * Removed dead code from `_.template`\n\nThe full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).\n\n## BestieJS\n\nLo-Dash is part of the BestieJS *âBest in Classâ* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.\n\n## Author\n\n* [John-David Dalton](http://allyoucanleet.com/)\n  [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton \"Follow @jdalton on Twitter\")\n\n## Contributors\n\n* [Kit Cambridge](http://kitcambridge.github.com/)\n  [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\")\n* [Mathias Bynens](http://mathiasbynens.be/)\n  [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias \"Follow @mathias on Twitter\")\n",
+  "readmeFilename": "README.md",
+  "_id": "lodash@1.0.1",
+  "_from": "lodash@~1.0.1"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/perf/perf.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/perf/perf.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/perf/perf.js	(revision 533)
@@ -0,0 +1,1724 @@
+(function(window) {
+
+  /** Use a single "load" function */
+  var load = typeof require == 'function' ? require : window.load;
+
+  /** The file path of the Lo-Dash file to test */
+  var filePath = (function() {
+    var min = 0;
+    var result = window.phantom
+      ? phantom.args
+      : (window.system
+          ? (min = 1, system.args)
+          : (window.process ? (min = 2, process.argv) : (window.arguments || []))
+        );
+
+    var last = result[result.length - 1];
+    result = (result.length > min && last != 'test.js') ? last : '../lodash.js';
+
+    try {
+      result = require('fs').realpathSync(result);
+    } catch(e) { }
+
+    return result;
+  }());
+
+  /** Load Benchmark.js */
+  var Benchmark =
+    window.Benchmark || (
+      Benchmark = load('../vendor/benchmark.js/benchmark.js') || window.Benchmark,
+      Benchmark.Benchmark || Benchmark
+    );
+
+  /** Load Lo-Dash */
+  var lodash =
+    window.lodash || (
+      lodash = load(filePath) || window._,
+      lodash = lodash._ || lodash,
+      lodash.noConflict()
+    );
+
+  /** Load Underscore */
+  var _ =
+    window._ || (
+      _ = load('../vendor/underscore/underscore.js') || window._,
+      _._ || _
+    );
+
+  /** Used to access the Firebug Lite panel (set by `run`) */
+  var fbPanel;
+
+  /** Used to score performance */
+  var score = { 'a': 0, 'b': 0 };
+
+  /** Used to queue benchmark suites */
+  var suites = [];
+
+  /** The `ui` object */
+  var ui = window.ui || {
+    'buildPath': basename(filePath, '.js'),
+    'otherPath': 'underscore'
+  };
+
+  /** The Lo-Dash build basename */
+  var buildName = basename(ui.buildPath, '.js');
+
+  /** The other library basename */
+  var otherName = basename(ui.otherPath, '.js');
+
+  /** Expose functions to the global object */
+  window._ = _;
+  window.Benchmark = Benchmark;
+  window.lodash = lodash;
+
+  /** Add `console.log()` support for Narwhal and RingoJS */
+  if (!window.console && window.print) {
+    window.console = { 'log': window.print };
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Gets the basename of the given `filePath`. If the file `extension` is passed,
+   * it will be removed from the basename.
+   *
+   * @private
+   * @param {String} path The file path to inspect.
+   * @param {String} extension The extension to remove.
+   * @returns {String} Returns the basename.
+   */
+  function basename(filePath, extension) {
+    var result = (filePath || '').split(/[\\/]/).pop();
+    return arguments.length < 2
+      ? result
+      : result.replace(RegExp(extension.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&') + '$'), '');
+  }
+
+  /**
+   * Gets the Hz, i.e. operations per second, of `bench` adjusted for the
+   * margin of error.
+   *
+   * @private
+   * @param {Object} bench The benchmark object.
+   * @returns {Number} Returns the adjusted Hz.
+   */
+  function getHz(bench) {
+    var result = 1 / (bench.stats.mean + bench.stats.moe);
+    return isFinite(result) ? result : 0;
+  }
+
+  /**
+   * Logs text to the console.
+   *
+   * @private
+   * @param {String} text The text to log.
+   */
+  function log(text) {
+    console.log(text + '');
+    if (fbPanel) {
+      // scroll the Firebug Lite panel down
+      fbPanel.scrollTop = fbPanel.scrollHeight;
+    }
+  }
+
+  /**
+   * Runs all benchmark suites.
+   *
+   * @private (@public in the browser)
+   */
+  function run() {
+    fbPanel = (fbPanel = window.document && document.getElementById('FirebugUI')) &&
+      (fbPanel = (fbPanel = fbPanel.contentWindow || fbPanel.contentDocument).document || fbPanel) &&
+      fbPanel.getElementById('fbPanel1');
+
+    log('\nSit back and relax, this may take a while.');
+    suites[0].run();
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  lodash.extend(Benchmark.Suite.options, {
+    'onStart': function() {
+      log('\n' + this.name + ':');
+    },
+    'onCycle': function(event) {
+      log(event.target);
+    },
+    'onComplete': function() {
+      var formatNumber = Benchmark.formatNumber,
+          fastest = this.filter('fastest'),
+          fastestHz = getHz(fastest[0]),
+          slowest = this.filter('slowest'),
+          slowestHz = getHz(slowest[0]),
+          aHz = getHz(this[0]),
+          bHz = getHz(this[1]);
+
+      if (fastest.length > 1) {
+        log('It\'s too close to call.');
+        aHz = bHz = slowestHz;
+      }
+      else {
+        var percent = ((fastestHz / slowestHz) - 1) * 100;
+
+        log(
+          fastest[0].name + ' is ' +
+          formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) +
+          '% faster.'
+        );
+      }
+      // add score adjusted for margin of error
+      score.a += aHz;
+      score.b += bHz;
+
+      // remove current suite from queue
+      suites.shift();
+
+      if (suites.length) {
+        // run next suite
+        suites[0].run();
+      }
+      else {
+        var fastestTotalHz = Math.max(score.a, score.b),
+            slowestTotalHz = Math.min(score.a, score.b),
+            totalPercent = formatNumber(Math.round(((fastestTotalHz  / slowestTotalHz) - 1) * 100)),
+            totalX = fastestTotalHz / slowestTotalHz,
+            message = 'is ' + totalPercent + '% ' + (totalX == 1 ? '' : '(' + formatNumber(totalX.toFixed(2)) + 'x) ') + 'faster than';
+
+        // report results
+        if (score.a >= score.b) {
+          log('\n' + buildName + ' ' + message + ' ' + otherName + '.');
+        } else {
+          log('\n' + otherName + ' ' + message + ' ' + buildName + '.');
+        }
+      }
+    }
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  lodash.extend(Benchmark.options, {
+    'async': true,
+    'setup': '\
+      var window = Function("return this || global")(),\
+          _ = window._,\
+          lodash = window.lodash,\
+          belt = this.name == "Lo-Dash" ? lodash : _;\
+      \
+      var index,\
+          date = new Date,\
+          limit = 20,\
+          regexp = /x/,\
+          object = {},\
+          objects = Array(limit),\
+          numbers = Array(limit),\
+          fourNumbers = [5, 25, 10, 30],\
+          nestedNumbers = [1, [2], [3, [[4]]]],\
+          twoNumbers = [12, 23];\
+      \
+      for (index = 0; index < limit; index++) {\
+        numbers[index] = index;\
+        object["key" + index] = index;\
+        objects[index] = { "num": index };\
+      }\
+      \
+      if (typeof bind != "undefined") {\
+        var contextObject = { "name": "moe" },\
+            ctor = function() {};\
+        \
+        var func = function(greeting, punctuation) {\
+          return greeting + ", " + this.name + (punctuation || ".");\
+        };\
+        \
+        var lodashBoundNormal = lodash.bind(func, contextObject),\
+            lodashBoundPartial = lodash.bind(func, contextObject, "hi");\
+        \
+        var _boundNormal = _.bind(func, contextObject),\
+            _boundPartial = _.bind(func, contextObject, "hi");\
+      }\
+      \
+      if (typeof bindAll != "undefined") {\
+        var bindAllObjects = Array(this.count),\
+            funcNames = belt.functions(lodash);\
+        \
+        // potentially expensive\n\
+        for (index = 0; index < this.count; index++) {\
+          bindAllObjects[index] = belt.reduce(funcNames, function(object, funcName) {\
+            object[funcName] = lodash[funcName];\
+            return object;\
+          }, {});\
+        }\
+      }\
+      if (typeof compact != "undefined") {\
+        var uncompacted = numbers.slice();\
+        uncompacted[2] = false;\
+        uncompacted[6] = null;\
+        uncompacted[18] = "";\
+      }\
+      \
+      if (typeof countBy != "undefined" || typeof omit != "undefined") {\
+        var wordToNumber = {\
+          "one": 1,\
+          "two": 2,\
+          "three": 3,\
+          "four": 4,\
+          "five": 5,\
+          "six": 6,\
+          "seven": 7,\
+          "eight": 8,\
+          "nine": 9,\
+          "ten": 10,\
+          "eleven": 11,\
+          "twelve": 12,\
+          "thirteen": 13,\
+          "fourteen": 14,\
+          "fifteen": 15,\
+          "sixteen": 16,\
+          "seventeen": 17,\
+          "eighteen": 18,\
+          "nineteen": 19,\
+          "twenty": 20,\
+          "twenty-one": 21,\
+          "twenty-two": 22,\
+          "twenty-three": 23,\
+          "twenty-four": 24,\
+          "twenty-five": 25,\
+          "twenty-six": 26,\
+          "twenty-seven": 27,\
+          "twenty-eight": 28,\
+          "twenty-nine": 29,\
+          "thirty": 30,\
+          "thirty-one": 31,\
+          "thirty-two": 32,\
+          "thirty-three": 33,\
+          "thirty-four": 34,\
+          "thirty-five": 35,\
+          "thirty-six": 36,\
+          "thirty-seven": 37,\
+          "thirty-eight": 38,\
+          "thirty-nine": 39,\
+          "forty": 40\
+        };\
+        \
+        var words = belt.keys(wordToNumber).slice(0, limit);\
+      }\
+      \
+      if (typeof isEqual != "undefined") {\
+        var objectOfPrimitives = {\
+          "boolean": true,\
+          "number": 1,\
+          "string": "a"\
+        };\
+        \
+        var objectOfObjects = {\
+          "boolean": new Boolean(true),\
+          "number": new Number(1),\
+          "string": new String("a")\
+        };\
+        \
+        var object2 = {},\
+            objects2 = Array(limit),\
+            numbers2 = Array(limit),\
+            nestedNumbers2 = [1, [2], [3, [[4]]]],\
+            nestedNumbers3 = [1, [2], [5, [[6]]]],\
+            simpleObject = { "a": 1 },\
+            simpleObject2 = { "a": 2 },\
+            simpleObjects = [simpleObject],\
+            simpleObjects2 = [simpleObject2],\
+            twoNumbers2 = [18, 27];\
+        \
+        for (index = 0; index < limit; index++) {\
+          object2["key" + index] = index;\
+          objects2[index] = { "num": index };\
+          numbers2[index] = index;\
+        }\
+      }\
+      \
+      if (typeof multiArrays != "undefined") {\
+        var twentyValues = Array(20),\
+            twentyValues2 = Array(20),\
+            twentyFiveValues = Array(25),\
+            twentyFiveValues2 = Array(25),\
+            thirtyValues = Array(30),\
+            thirtyValues2 = Array(30),\
+            fortyValues = Array(40),\
+            fortyValues2 = Array(40),\
+            fiftyValues = Array(50),\
+            fiftyValues2 = Array(50),\
+            seventyFiveValues = Array(75),\
+            seventyFiveValues2 = Array(75),\
+            hundredValues = Array(100),\
+            hundredValues2 = Array(100),\
+            lowerChars = "abcdefghijklmnopqrstuvwxyz".split(""),\
+            upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");\
+        \
+        for (index = 0; index < 100; index++) {\
+          if (index < 15) {\
+            twentyValues[index] = lowerChars[index];\
+            twentyValues2[index] = upperChars[index];\
+          }\
+          if (index < 20) {\
+            twentyValues[index] =\
+            twentyValues2[index] = index;\
+            \
+            twentyFiveValues[index] = lowerChars[index];\
+            twentyFiveValues2[index] = upperChars[index];\
+          }\
+          if (index < 25) {\
+            twentyFiveValues[index] =\
+            twentyFiveValues2[index] = index;\
+            \
+            thirtyValues[index] =\
+            fortyValues[index] =\
+            fiftyValues[index] =\
+            seventyFiveValues[index] =\
+            hundredValues[index] = lowerChars[index];\
+            \
+            thirtyValues2[index] =\
+            fortyValues2[index] =\
+            fiftyValues2[index] =\
+            seventyFiveValues2[index] =\
+            hundredValues2[index] = upperChars[index];\
+          }\
+          else {\
+            if (index < 30) {\
+              thirtyValues[index] =\
+              thirtyValues2[index] = index;\
+            }\
+            if (index < 40) {\
+              fortyValues[index] =\
+              fortyValues2[index] = index;\
+            }\
+            if (index < 50) {\
+              fiftyValues[index] =\
+              fiftyValues2[index] = index;\
+            }\
+            if (index < 75) {\
+              seventyFiveValues[index] =\
+              seventyFiveValues2[index] = index;\
+            }\
+            hundredValues[index] =\
+            hundredValues2[index] = index;\
+          }\
+        }\
+      }\
+      \
+      if (typeof template != "undefined") {\
+        var tplData = {\
+          "header1": "Header1",\
+          "header2": "Header2",\
+          "header3": "Header3",\
+          "header4": "Header4",\
+          "header5": "Header5",\
+          "header6": "Header6",\
+          "list": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]\
+        };\
+        \
+        var tpl =\
+          "<div>" +\
+          "<h1 class=\'header1\'><%= header1 %></h1>" +\
+          "<h2 class=\'header2\'><%= header2 %></h2>" +\
+          "<h3 class=\'header3\'><%= header3 %></h3>" +\
+          "<h4 class=\'header4\'><%= header4 %></h4>" +\
+          "<h5 class=\'header5\'><%= header5 %></h5>" +\
+          "<h6 class=\'header6\'><%= header6 %></h6>" +\
+          "<ul class=\'list\'>" +\
+          "<% for (var index = 0, length = list.length; index < length; index++) { %>" +\
+          "<li class=\'item\'><%= list[index] %></li>" +\
+          "<% } %>" +\
+          "</ul>" +\
+          "</div>";\
+        \
+        var tplVerbose =\
+          "<div>" +\
+          "<h1 class=\'header1\'><%= data.header1 %></h1>" +\
+          "<h2 class=\'header2\'><%= data.header2 %></h2>" +\
+          "<h3 class=\'header3\'><%= data.header3 %></h3>" +\
+          "<h4 class=\'header4\'><%= data.header4 %></h4>" +\
+          "<h5 class=\'header5\'><%= data.header5 %></h5>" +\
+          "<h6 class=\'header6\'><%= data.header6 %></h6>" +\
+          "<ul class=\'list\'>" +\
+          "<% for (var index = 0, length = data.list.length; index < length; index++) { %>" +\
+          "<li class=\'item\'><%= data.list[index] %></li>" +\
+          "<% } %>" +\
+          "</ul>" +\
+          "</div>";\
+        \
+        var settingsObject = { "variable": "data" };\
+        \
+        var lodashTpl = lodash.template(tpl),\
+            lodashTplVerbose = lodash.template(tplVerbose, null, settingsObject);\
+        \
+        var _tpl = _.template(tpl),\
+            _tplVerbose = _.template(tplVerbose, null, settingsObject);\
+      }'
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.bind` (uses native `Function#bind` if available and inferred fast)')
+      .add(buildName, {
+        'fn': 'lodash.bind(func, { "name": "moe" }, "hi")',
+        'teardown': 'function bind(){}'
+      })
+      .add(otherName, {
+        'fn': '_.bind(func, { "name": "moe" }, "hi")',
+        'teardown': 'function bind(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('bound call')
+      .add(buildName, {
+        'fn': 'lodashBoundNormal()',
+        'teardown': 'function bind(){}'
+      })
+      .add(otherName, {
+        'fn': '_boundNormal()',
+        'teardown': 'function bind(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('bound call with arguments')
+      .add(buildName, {
+        'fn': 'lodashBoundNormal("hi", "!")',
+        'teardown': 'function bind(){}'
+      })
+      .add(otherName, {
+        'fn': '_boundNormal("hi", "!")',
+        'teardown': 'function bind(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('bound and partially applied call (uses native `Function#bind` if available)')
+      .add(buildName, {
+        'fn': 'lodashBoundPartial()',
+        'teardown': 'function bind(){}'
+      })
+      .add(otherName, {
+        'fn': '_boundPartial()',
+        'teardown': 'function bind(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('bound and partially applied call with arguments (uses native `Function#bind` if available)')
+      .add(buildName, {
+        'fn': 'lodashBoundPartial("!")',
+        'teardown': 'function bind(){}'
+      })
+      .add(otherName, {
+        'fn': '_boundPartial("!")',
+        'teardown': 'function bind(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.bindAll` iterating arguments')
+      .add(buildName, {
+        'fn': 'lodash.bindAll.apply(lodash, [bindAllObjects.pop()].concat(funcNames))',
+        'teardown': 'function bindAll(){}'
+      })
+      .add(otherName, {
+        'fn': '_.bindAll.apply(_, [bindAllObjects.pop()].concat(funcNames))',
+        'teardown': 'function bindAll(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.bindAll` iterating the `object`')
+      .add(buildName, {
+        'fn': 'lodash.bindAll(bindAllObjects.pop())',
+        'teardown': 'function bindAll(){}'
+      })
+      .add(otherName, {
+        'fn': '_.bindAll(bindAllObjects.pop())',
+        'teardown': 'function bindAll(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.clone` with an object')
+      .add(buildName, '\
+        lodash.clone(object)'
+      )
+      .add(otherName, '\
+        _.clone(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.compact`')
+      .add(buildName, {
+        'fn': 'lodash.compact(uncompacted)',
+        'teardown': 'function compact(){}'
+      })
+      .add(otherName, {
+        'fn': '_.compact(uncompacted)',
+        'teardown': 'function compact(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.contains` iterating an array')
+      .add(buildName, '\
+        lodash.contains(numbers, 19)'
+      )
+      .add(otherName, '\
+        _.contains(numbers, 19)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.contains` iterating an object')
+      .add(buildName, '\
+        lodash.contains(object, 19)'
+      )
+      .add(otherName, '\
+        _.contains(object, 19)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.countBy` with `callback` iterating an array')
+      .add(buildName, '\
+        lodash.countBy(numbers, function(num) { return num >> 1; })'
+      )
+      .add(otherName, '\
+        _.countBy(numbers, function(num) { return num >> 1; })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.countBy` with `property` name iterating an array')
+      .add(buildName, {
+        'fn': 'lodash.countBy(words, "length")',
+        'teardown': 'function countBy(){}'
+      })
+      .add(otherName, {
+        'fn': '_.countBy(words, "length")',
+        'teardown': 'function countBy(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.countBy` with `callback` iterating an object')
+      .add(buildName, {
+        'fn': 'lodash.countBy(wordToNumber, function(num) { return num >> 1; })',
+        'teardown': 'function countBy(){}'
+      })
+      .add(otherName, {
+        'fn': '_.countBy(wordToNumber, function(num) { return num >> 1; })',
+        'teardown': 'function countBy(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.defaults`')
+      .add(buildName, '\
+        lodash.defaults({ "key2": 2, "key6": 6, "key18": 18 }, object)'
+      )
+      .add(otherName, '\
+        _.defaults({ "key2": 2, "key6": 6, "key18": 18 }, object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.difference`')
+      .add(buildName, '\
+        lodash.difference(numbers, twoNumbers, fourNumbers)'
+      )
+      .add(otherName, '\
+        _.difference(numbers, twoNumbers, fourNumbers)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.difference` iterating 30 elements')
+      .add(buildName, {
+        'fn': 'lodash.difference(thirtyValues, thirtyValues2)',
+        'teardown': 'function multiArrays(){}'
+      })
+      .add(otherName, {
+        'fn': '_.difference(thirtyValues, thirtyValues2)',
+        'teardown': 'function multiArrays(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.difference` iterating 20 and 40 elements')
+      .add(buildName, {
+        'fn': 'lodash.difference(twentyValues, fortyValues2)',
+        'teardown': 'function multiArrays(){}'
+      })
+      .add(otherName, {
+        'fn': '_.difference(twentyValues, fortyValues2)',
+        'teardown': 'function multiArrays(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.each` iterating an array')
+      .add(buildName, '\
+        var result = [];\
+        lodash.each(numbers, function(num) {\
+          result.push(num * 2);\
+        })'
+      )
+      .add(otherName, '\
+        var result = [];\
+        _.each(numbers, function(num) {\
+          result.push(num * 2);\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.each` iterating an array with `thisArg` (slow path)')
+      .add(buildName, '\
+        var result = [];\
+        lodash.each(numbers, function(num, index) {\
+          result.push(num + this["key" + index]);\
+        }, object)'
+      )
+      .add(otherName, '\
+        var result = [];\
+        _.each(numbers, function(num, index) {\
+          result.push(num + this["key" + index]);\
+        }, object)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.each` iterating an object')
+      .add(buildName, '\
+        var result = [];\
+        lodash.each(object, function(num) {\
+          result.push(num * 2);\
+        })'
+      )
+      .add(otherName, '\
+        var result = [];\
+        _.each(object, function(num) {\
+          result.push(num * 2);\
+        })'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.every` iterating an array')
+      .add(buildName, '\
+        lodash.every(numbers, function(num) {\
+          return num + "";\
+        })'
+      )
+      .add(otherName, '\
+        _.every(numbers, function(num) {\
+          return num + "";\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.every` iterating an object')
+      .add(buildName, '\
+        lodash.every(object, function(num) {\
+          return num + "";\
+        })'
+      )
+      .add(otherName, '\
+        _.every(object, function(num) {\
+          return num + "";\
+        })'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.extend`')
+      .add(buildName, '\
+        lodash.extend({}, object)'
+      )
+      .add(otherName, '\
+        _.extend({}, object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.filter` iterating an array')
+      .add(buildName, '\
+        lodash.filter(numbers, function(num) {\
+          return num % 2;\
+        })'
+      )
+      .add(otherName, '\
+        _.filter(numbers, function(num) {\
+          return num % 2;\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.filter` iterating an array with `thisArg` (slow path)')
+      .add(buildName, '\
+        lodash.filter(numbers, function(num, index) {\
+          return this["key" + index] % 2;\
+        }, object)'
+      )
+      .add(otherName, '\
+        _.filter(numbers, function(num, index) {\
+           return this["key" + index] % 2;\
+        }, object)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.filter` iterating an object')
+      .add(buildName, '\
+        lodash.filter(object, function(num) {\
+          return num % 2\
+        })'
+      )
+      .add(otherName, '\
+        _.filter(object, function(num) {\
+          return num % 2\
+        })'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.find` iterating an array')
+      .add(buildName, '\
+        lodash.find(numbers, function(num) {\
+          return num === 19;\
+        })'
+      )
+      .add(otherName, '\
+        _.find(numbers, function(num) {\
+          return num === 19;\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.find` iterating an object')
+      .add(buildName, '\
+        lodash.find(object, function(value, key) {\
+          return /\D9$/.test(key);\
+        })'
+      )
+      .add(otherName, '\
+        _.find(object, function(value, key) {\
+          return /\D9$/.test(key);\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.find` with `properties`')
+      .add(buildName, '\
+        lodash.find(objects, { "num": 9 });'
+      )
+      .add(otherName, '\
+        _.findWhere(objects, { "num": 9 });'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.flatten`')
+      .add(buildName, '\
+        lodash.flatten(nestedNumbers)'
+      )
+      .add(otherName, '\
+        _.flatten(nestedNumbers)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.flatten` with `shallow`')
+      .add(buildName, '\
+        lodash.flatten(nestedNumbers, true)'
+      )
+      .add(otherName, '\
+        _.flatten(nestedNumbers, true)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.functions`')
+      .add(buildName, '\
+        lodash.functions(lodash)'
+      )
+      .add(otherName, '\
+        _.functions(lodash)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.groupBy` with `callback` iterating an array')
+      .add(buildName, '\
+        lodash.groupBy(numbers, function(num) { return num >> 1; })'
+      )
+      .add(otherName, '\
+        _.groupBy(numbers, function(num) { return num >> 1; })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.groupBy` with `property` name iterating an array')
+      .add(buildName, {
+        'fn': 'lodash.groupBy(words, "length")',
+        'teardown': 'function countBy(){}'
+      })
+      .add(otherName, {
+        'fn': '_.groupBy(words, "length")',
+        'teardown': 'function countBy(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.groupBy` with `callback` iterating an object')
+      .add(buildName, {
+        'fn': 'lodash.groupBy(wordToNumber, function(num) { return num >> 1; })',
+        'teardown': 'function countBy(){}'
+      })
+      .add(otherName, {
+        'fn': '_.groupBy(wordToNumber, function(num) { return num >> 1; })',
+        'teardown': 'function countBy(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.indexOf`')
+      .add(buildName, '\
+        lodash.indexOf(numbers, 9)'
+      )
+      .add(otherName, '\
+        _.indexOf(numbers, 9)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.indexOf` with `isSorted`')
+      .add(buildName, '\
+        lodash.indexOf(numbers, 19, true)'
+      )
+      .add(otherName, '\
+        _.indexOf(numbers, 19, true)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.intersection`')
+      .add(buildName, '\
+        lodash.intersection(numbers, twoNumbers, fourNumbers)'
+      )
+      .add(otherName, '\
+        _.intersection(numbers, twoNumbers, fourNumbers)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.intersection` iterating 100 elements')
+      .add(buildName, {
+        'fn': 'lodash.intersection(hundredValues, hundredValues2)',
+        'teardown': 'function multiArrays(){}'
+      })
+      .add(otherName, {
+        'fn': '_.intersection(hundredValues, hundredValues2)',
+        'teardown': 'function multiArrays(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.invert`')
+      .add(buildName, '\
+        lodash.invert(object)'
+      )
+      .add(otherName, '\
+        _.invert(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.invoke` iterating an array')
+      .add(buildName, '\
+        lodash.invoke(numbers, "toFixed", "2")'
+      )
+      .add(otherName, '\
+        _.invoke(numbers, "toFixed", "2")'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.invoke` with a function for `methodName` iterating an array')
+      .add(buildName, '\
+        lodash.invoke(numbers, String.prototype.split, "")'
+      )
+      .add(otherName, '\
+        _.invoke(numbers, String.prototype.split, "")'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.invoke` iterating an object')
+      .add(buildName, '\
+        lodash.invoke(object, "toFixed", "2")'
+      )
+      .add(otherName, '\
+        _.invoke(object, "toFixed", "2")'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.isEqual` comparing primitives and objects (edge case)')
+      .add(buildName, {
+        'fn': 'lodash.isEqual(objectOfPrimitives, objectOfObjects)',
+        'teardown': 'function isEqual(){}'
+      })
+      .add(otherName, {
+        'fn': '_.isEqual(objectOfPrimitives, objectOfObjects)',
+        'teardown': 'function isEqual(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.isEqual` comparing arrays')
+      .add(buildName, {
+        'fn': '\
+          lodash.isEqual(numbers, numbers2);\
+          lodash.isEqual(twoNumbers, twoNumbers2);',
+        'teardown': 'function isEqual(){}'
+      })
+      .add(otherName, {
+        'fn': '\
+          _.isEqual(numbers, numbers2);\
+          _.isEqual(twoNumbers, twoNumbers2);',
+        'teardown': 'function isEqual(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.isEqual` comparing nested arrays')
+      .add(buildName, {
+        'fn': '\
+          lodash.isEqual(nestedNumbers, nestedNumbers2);\
+          lodash.isEqual(nestedNumbers2, nestedNumbers3);',
+        'teardown': 'function isEqual(){}'
+      })
+      .add(otherName, {
+        'fn': '\
+          _.isEqual(nestedNumbers, nestedNumbers2);\
+          _.isEqual(nestedNumbers2, nestedNumbers3);',
+        'teardown': 'function isEqual(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.isEqual` comparing arrays of objects')
+      .add(buildName, {
+        'fn': '\
+          lodash.isEqual(objects, objects2);\
+          lodash.isEqual(simpleObjects, simpleObjects2);',
+        'teardown': 'function isEqual(){}'
+      })
+      .add(otherName, {
+        'fn': '\
+          _.isEqual(objects, objects2);\
+          _.isEqual(simpleObjects, simpleObjects2);',
+        'teardown': 'function isEqual(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.isEqual` comparing objects')
+      .add(buildName, {
+        'fn': '\
+          lodash.isEqual(object, object2);\
+          lodash.isEqual(simpleObject, simpleObject2);',
+        'teardown': 'function isEqual(){}'
+      })
+      .add(otherName, {
+        'fn': '\
+          _.isEqual(object, object2);\
+          _.isEqual(simpleObject, simpleObject2);',
+        'teardown': 'function isEqual(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.isArguments`, `_.isDate`, `_.isFunction`, `_.isNumber`, `_.isRegExp`')
+      .add(buildName, '\
+        lodash.isArguments(arguments);\
+        lodash.isArguments(object);\
+        lodash.isDate(date);\
+        lodash.isDate(object);\
+        lodash.isFunction(lodash);\
+        lodash.isFunction(object);\
+        lodash.isNumber(1);\
+        lodash.isNumber(object);\
+        lodash.isRegExp(regexp);\
+        lodash.isRegExp(object);'
+      )
+      .add(otherName, '\
+        _.isArguments(arguments);\
+        _.isArguments(object);\
+        _.isDate(date);\
+        _.isDate(object);\
+        _.isFunction(_);\
+        _.isFunction(object);\
+        _.isNumber(1);\
+        _.isNumber(object);\
+        _.isRegExp(regexp);\
+        _.isRegExp(object);'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.keys` (uses native `Object.keys` if available)')
+      .add(buildName, '\
+        lodash.keys(object)'
+      )
+      .add(otherName, '\
+        _.keys(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.lastIndexOf`')
+      .add(buildName, '\
+        lodash.lastIndexOf(numbers, 9)'
+      )
+      .add(otherName, '\
+        _.lastIndexOf(numbers, 9)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.map` iterating an array')
+      .add(buildName, '\
+        lodash.map(objects, function(value) {\
+          return value.num;\
+        })'
+      )
+      .add(otherName, '\
+        _.map(objects, function(value) {\
+          return value.num;\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.map` with `thisArg` iterating an array (slow path)')
+      .add(buildName, '\
+        lodash.map(objects, function(value, index) {\
+          return this["key" + index] + value.num;\
+        }, object)'
+      )
+      .add(otherName, '\
+        _.map(objects, function(value, index) {\
+          return this["key" + index] + value.num;\
+        }, object)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.map` iterating an object')
+      .add(buildName, '\
+        lodash.map(object, function(value) {\
+          return value;\
+        })'
+      )
+      .add(otherName, '\
+        _.map(object, function(value) {\
+          return value;\
+        })'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.max`')
+      .add(buildName, '\
+        lodash.max(numbers)'
+      )
+      .add(otherName, '\
+        _.max(numbers)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.min`')
+      .add(buildName, '\
+        lodash.min(numbers)'
+      )
+      .add(otherName, '\
+        _.min(numbers)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.omit` iterating 20 properties, omitting 2 keys')
+      .add(buildName, '\
+        lodash.omit(object, "key6", "key13")'
+      )
+      .add(otherName, '\
+        _.omit(object, "key6", "key13")'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.omit` iterating 40 properties, omitting 20 keys')
+      .add(buildName, {
+        'fn': 'lodash.omit(wordToNumber, words)',
+        'teardown': 'function omit(){}'
+      })
+      .add(otherName, {
+        'fn': 'result = _.omit(wordToNumber, words)',
+        'teardown': 'function omit(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.pairs`')
+      .add(buildName, '\
+        lodash.pairs(object)'
+      )
+      .add(otherName, '\
+        _.pairs(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.pick`')
+      .add(buildName, '\
+        lodash.pick(object, "key6", "key13")'
+      )
+      .add(otherName, '\
+        _.pick(object, "key6", "key13")'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.pluck`')
+      .add(buildName, '\
+        lodash.pluck(objects, "num")'
+      )
+      .add(otherName, '\
+        _.pluck(objects, "num")'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.reduce` iterating an array')
+      .add(buildName, '\
+        lodash.reduce(numbers, function(result, value, index) {\
+          result[index] = value;\
+          return result;\
+        }, {});'
+      )
+      .add(otherName, '\
+        _.reduce(numbers, function(result, value, index) {\
+          result[index] = value;\
+          return result;\
+        }, {});'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.reduce` iterating an object')
+      .add(buildName, '\
+        lodash.reduce(object, function(result, value, key) {\
+          result.push([key, value]);\
+          return result;\
+        }, []);'
+      )
+      .add(otherName, '\
+        _.reduce(object, function(result, value, key) {\
+          result.push([key, value]);\
+          return result;\
+        }, []);'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.reduceRight` iterating an array')
+      .add(buildName, '\
+        lodash.reduceRight(numbers, function(result, value, index) {\
+          result[index] = value;\
+          return result;\
+        }, {});'
+      )
+      .add(otherName, '\
+        _.reduceRight(numbers, function(result, value, index) {\
+          result[index] = value;\
+          return result;\
+        }, {});'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.reduceRight` iterating an object')
+      .add(buildName, '\
+        lodash.reduceRight(object, function(result, value, key) {\
+          result.push([key, value]);\
+          return result;\
+        }, []);'
+      )
+      .add(otherName, '\
+        _.reduceRight(object, function(result, value, key) {\
+          result.push([key, value]);\
+          return result;\
+        }, []);'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.reject` iterating an array')
+      .add(buildName, '\
+        lodash.reject(numbers, function(num) {\
+          return num % 2;\
+        })'
+      )
+      .add(otherName, '\
+        _.reject(numbers, function(num) {\
+          return num % 2;\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.reject` iterating an array with `thisArg` (slow path)')
+      .add(buildName, '\
+        lodash.reject(numbers, function(num, index) {\
+          return this["key" + index] % 2;\
+        }, object)'
+      )
+      .add(otherName, '\
+        _.reject(numbers, function(num, index) {\
+           return this["key" + index] % 2;\
+        }, object)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.reject` iterating an object')
+      .add(buildName, '\
+        lodash.reject(object, function(num) {\
+          return num % 2\
+        })'
+      )
+      .add(otherName, '\
+        _.reject(object, function(num) {\
+          return num % 2\
+        })'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.shuffle`')
+      .add(buildName, '\
+        lodash.shuffle(numbers)'
+      )
+      .add(otherName, '\
+        _.shuffle(numbers)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.size` with an object')
+      .add(buildName, '\
+        lodash.size(object)'
+      )
+      .add(otherName, '\
+        _.size(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.some` iterating an array')
+      .add(buildName, '\
+        lodash.some(numbers, function(num) {\
+          return num == 19;\
+        })'
+      )
+      .add(otherName, '\
+        _.some(numbers, function(num) {\
+          return num == 19;\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.some` with `thisArg` iterating an array (slow path)')
+      .add(buildName, '\
+        lodash.some(objects, function(value, index) {\
+          return this["key" + index] == 19;\
+        }, object)'
+      )
+      .add(otherName, '\
+        _.some(objects, function(value, index) {\
+          return this["key" + index] == 19;\
+        }, object)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.some` iterating an object')
+      .add(buildName, '\
+        lodash.some(object, function(num) {\
+          return num == 19;\
+        })'
+      )
+      .add(otherName, '\
+        _.some(object, function(num) {\
+          return num == 19;\
+        })'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.sortBy` with `callback`')
+      .add(buildName, '\
+        lodash.sortBy(numbers, function(num) { return Math.sin(num); })'
+      )
+      .add(otherName, '\
+        _.sortBy(numbers, function(num) { return Math.sin(num); })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.sortBy` with `callback` and `thisArg` (slow path)')
+      .add(buildName, '\
+        lodash.sortBy(numbers, function(num) { return this.sin(num); }, Math)'
+      )
+      .add(otherName, '\
+        _.sortBy(numbers, function(num) { return this.sin(num); }, Math)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.sortBy` with `property` name')
+      .add(buildName, {
+        'fn': 'lodash.sortBy(words, "length")',
+        'teardown': 'function countBy(){}'
+      })
+      .add(otherName, {
+        'fn': '_.sortBy(words, "length")',
+        'teardown': 'function countBy(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.sortedIndex`')
+      .add(buildName, '\
+        lodash.sortedIndex(numbers, 25)'
+      )
+      .add(otherName, '\
+        _.sortedIndex(numbers, 25)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.sortedIndex` with `callback`')
+      .add(buildName, {
+        'fn': '\
+          lodash.sortedIndex(words, "twenty-five", function(value) {\
+            return wordToNumber[value];\
+          })',
+        'teardown': 'function countBy(){}'
+      })
+      .add(otherName, {
+        'fn': '\
+          _.sortedIndex(words, "twenty-five", function(value) {\
+            return wordToNumber[value];\
+          })',
+        'teardown': 'function countBy(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.template` (slow path)')
+      .add(buildName, {
+        'fn': 'lodash.template(tpl, tplData)',
+        'teardown': 'function template(){}'
+      })
+      .add(otherName, {
+        'fn': '_.template(tpl, tplData)',
+        'teardown': 'function template(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('compiled template')
+      .add(buildName, {
+        'fn': 'lodashTpl(tplData)',
+        'teardown': 'function template(){}'
+      })
+      .add(otherName, {
+        'fn': '_tpl(tplData)',
+        'teardown': 'function template(){}'
+      })
+  );
+
+  suites.push(
+    Benchmark.Suite('compiled template without a with-statement')
+      .add(buildName, {
+        'fn': 'lodashTplVerbose(tplData)',
+        'teardown': 'function template(){}'
+      })
+      .add(otherName, {
+        'fn': '_tplVerbose(tplData)',
+        'teardown': 'function template(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.times`')
+      .add(buildName, '\
+        var result = [];\
+        lodash.times(limit, function(n) { result.push(n); })'
+      )
+      .add(otherName, '\
+        var result = [];\
+        _.times(limit, function(n) { result.push(n); })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.times` with `thisArg`')
+      .add(buildName, '\
+        var result = [];\
+        lodash.times(limit, function(n) { result.push(this.sin(n)); }, Math)'
+      )
+      .add(otherName, '\
+        var result = [];\
+        _.times(limit, function(n) { result.push(this.sin(n)); }, Math)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.toArray` with an array (edge case)')
+      .add(buildName, '\
+        lodash.toArray(numbers)'
+      )
+      .add(otherName, '\
+        _.toArray(numbers)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.toArray` with an object')
+      .add(buildName, '\
+        lodash.toArray(object)'
+      )
+      .add(otherName, '\
+        _.toArray(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.union`')
+      .add(buildName, '\
+        lodash.union(numbers, twoNumbers, fourNumbers)'
+      )
+      .add(otherName, '\
+        _.union(numbers, twoNumbers, fourNumbers)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.union` iterating an array of 75 elements')
+      .add(buildName, {
+        'fn': 'lodash.union(fiftyValues, twentyFiveValues2);',
+        'teardown': 'function multiArrays(){}'
+      })
+      .add(otherName, {
+        'fn': '_.union(fiftyValues, twentyFiveValues2);',
+        'teardown': 'function multiArrays(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.uniq`')
+      .add(buildName, '\
+        lodash.uniq(numbers.concat(twoNumbers, fourNumbers))'
+      )
+      .add(otherName, '\
+        _.uniq(numbers.concat(twoNumbers, fourNumbers))'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.uniq` with `callback`')
+      .add(buildName, '\
+        lodash.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\
+          return num % 2;\
+        });'
+      )
+      .add(otherName, '\
+        _.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\
+          return num % 2;\
+        })'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.uniq` iterating an array of 75 elements')
+      .add(buildName, {
+        'fn': 'lodash.uniq(fiftyValues.concat(twentyFiveValues2));',
+        'teardown': 'function multiArrays(){}'
+      })
+      .add(otherName, {
+        'fn': '_.uniq(fiftyValues.concat(twentyFiveValues2));',
+        'teardown': 'function multiArrays(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.values`')
+      .add(buildName, '\
+        lodash.values(object)'
+      )
+      .add(otherName, '\
+        _.values(object)'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.where`')
+      .add(buildName, '\
+        lodash.where(objects, { "num": 9 });'
+      )
+      .add(otherName, '\
+        _.where(objects, { "num": 9 });'
+      )
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  suites.push(
+    Benchmark.Suite('`_.without`')
+      .add(buildName, '\
+        lodash.without(numbers, 9, 12, 14, 15)'
+      )
+      .add(otherName, '\
+        _.without(numbers, 9, 12, 14, 15)'
+      )
+  );
+
+  suites.push(
+    Benchmark.Suite('`_.without` iterating an array of 30 elements')
+      .add(buildName, {
+        'fn': 'lodash.without.apply(lodash, [thirtyValues].concat(thirtyValues2));',
+        'teardown': 'function multiArrays(){}'
+      })
+      .add(otherName, {
+        'fn': '_.without.apply(_, [thirtyValues].concat(thirtyValues2));',
+        'teardown': 'function multiArrays(){}'
+      })
+  );
+
+  /*--------------------------------------------------------------------------*/
+
+  if (Benchmark.platform + '') {
+    log(Benchmark.platform);
+  }
+
+  // in the browser, expose `run` to be called later
+  if (window.document && !window.phantom) {
+    window.run = run;
+  } else {
+    run();
+  }
+}(typeof global == 'object' && global || this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/a.jst
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/a.jst	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/a.jst	(revision 533)
@@ -0,0 +1,3 @@
+<ul>
+<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>
+</ul>
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/b.jst
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/b.jst	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/b.jst	(revision 533)
@@ -0,0 +1,1 @@
+<% print("Hello " + epithet); %>.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/c.jst
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/c.jst	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/c.jst	(revision 533)
@@ -0,0 +1,1 @@
+Hello ${ name }!
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/d.tpl
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/d.tpl	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/d.tpl	(revision 533)
@@ -0,0 +1,1 @@
+Hello {{ name }}!
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test-build.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test-build.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test-build.js	(revision 533)
@@ -0,0 +1,1324 @@
+#!/usr/bin/env node
+;(function(undefined) {
+  'use strict';
+
+  /** Load modules */
+  var fs = require('fs'),
+      path = require('path'),
+      vm = require('vm'),
+      build = require('../build.js'),
+      minify = require('../build/minify'),
+      _ = require('../lodash.js');
+
+  /** The unit testing framework */
+  var QUnit = (
+    global.addEventListener || (global.addEventListener = Function.prototype),
+    global.QUnit = require('../vendor/qunit/qunit/qunit.js'),
+    require('../vendor/qunit-clib/qunit-clib.js'),
+    global.addEventListener === Function.prototype && delete global.addEventListener,
+    global.QUnit
+  );
+
+  /** The time limit for the tests to run (milliseconds) */
+  var timeLimit = process.argv.reduce(function(result, value, index) {
+    if (/--time-limit/.test(value)) {
+      return parseInt(process.argv[index + 1].replace(/(\d+h)?(\d+m)?(\d+s)?/, function(match, h, m, s) {
+        return ((parseInt(h) || 0) * 3600000) +
+               ((parseInt(m) || 0) * 60000) +
+               ((parseInt(s) || 0) * 1000);
+      })) || result;
+    }
+    return result;
+  }, 0);
+
+  /** Used to associate aliases with their real names */
+  var aliasToRealMap = {
+    'all': 'every',
+    'any': 'some',
+    'collect': 'map',
+    'detect': 'find',
+    'drop': 'rest',
+    'each': 'forEach',
+    'extend': 'assign',
+    'foldl': 'reduce',
+    'foldr': 'reduceRight',
+    'head': 'first',
+    'include': 'contains',
+    'inject': 'reduce',
+    'methods': 'functions',
+    'select': 'filter',
+    'tail': 'rest',
+    'take': 'first',
+    'unique': 'uniq'
+  };
+
+  /** Used to associate real names with their aliases */
+  var realToAliasMap = {
+    'assign': ['extend'],
+    'contains': ['include'],
+    'every': ['all'],
+    'filter': ['select'],
+    'find': ['detect'],
+    'first': ['head', 'take'],
+    'forEach': ['each'],
+    'functions': ['methods'],
+    'map': ['collect'],
+    'reduce': ['foldl', 'inject'],
+    'reduceRight': ['foldr'],
+    'rest': ['drop', 'tail'],
+    'some': ['any'],
+    'uniq': ['unique']
+  };
+
+  /** List of all Lo-Dash methods */
+  var allMethods = _.functions(_)
+    .filter(function(methodName) { return !/^_/.test(methodName); })
+    .concat('chain')
+    .sort();
+
+  /** List of "Arrays" category methods */
+  var arraysMethods = [
+    'compact',
+    'difference',
+    'drop',
+    'first',
+    'flatten',
+    'head',
+    'indexOf',
+    'initial',
+    'intersection',
+    'last',
+    'lastIndexOf',
+    'object',
+    'range',
+    'rest',
+    'sortedIndex',
+    'tail',
+    'take',
+    'union',
+    'uniq',
+    'unique',
+    'without',
+    'zip'
+  ];
+
+  /** List of "Chaining" category methods */
+  var chainingMethods = [
+    'mixin',
+    'tap',
+    'value'
+  ];
+
+  /** List of "Collections" category methods */
+  var collectionsMethods = [
+    'all',
+    'any',
+    'at',
+    'collect',
+    'contains',
+    'countBy',
+    'detect',
+    'each',
+    'every',
+    'filter',
+    'find',
+    'foldl',
+    'foldr',
+    'forEach',
+    'groupBy',
+    'include',
+    'inject',
+    'invoke',
+    'map',
+    'max',
+    'min',
+    'pluck',
+    'reduce',
+    'reduceRight',
+    'reject',
+    'select',
+    'shuffle',
+    'size',
+    'some',
+    'sortBy',
+    'toArray',
+    'where'
+  ];
+
+  /** List of "Functions" category methods */
+  var functionsMethods = [
+    'after',
+    'bind',
+    'bindAll',
+    'bindKey',
+    'compose',
+    'debounce',
+    'defer',
+    'delay',
+    'memoize',
+    'once',
+    'partial',
+    'partialRight',
+    'throttle',
+    'wrap'
+  ];
+
+  /** List of "Objects" category methods */
+  var objectsMethods = [
+    'assign',
+    'clone',
+    'cloneDeep',
+    'defaults',
+    'extend',
+    'forIn',
+    'forOwn',
+    'functions',
+    'has',
+    'invert',
+    'isArguments',
+    'isArray',
+    'isBoolean',
+    'isDate',
+    'isElement',
+    'isEmpty',
+    'isEqual',
+    'isFinite',
+    'isFunction',
+    'isNaN',
+    'isNull',
+    'isNumber',
+    'isObject',
+    'isPlainObject',
+    'isRegExp',
+    'isString',
+    'isUndefined',
+    'keys',
+    'methods',
+    'merge',
+    'omit',
+    'pairs',
+    'pick',
+    'values'
+  ];
+
+  /** List of "Utilities" category methods */
+  var utilityMethods = [
+    'escape',
+    'identity',
+    'noConflict',
+    'random',
+    'result',
+    'template',
+    'times',
+    'unescape',
+    'uniqueId'
+  ];
+
+  /** List of Backbone's Lo-Dash dependencies */
+  var backboneDependencies = [
+    'bind',
+    'bindAll',
+    'chain',
+    'clone',
+    'contains',
+    'countBy',
+    'defaults',
+    'escape',
+    'every',
+    'extend',
+    'filter',
+    'find',
+    'first',
+    'forEach',
+    'groupBy',
+    'has',
+    'indexOf',
+    'initial',
+    'invoke',
+    'isArray',
+    'isEmpty',
+    'isEqual',
+    'isFunction',
+    'isObject',
+    'isRegExp',
+    'isString',
+    'keys',
+    'last',
+    'lastIndexOf',
+    'map',
+    'max',
+    'min',
+    'mixin',
+    'once',
+    'pick',
+    'reduce',
+    'reduceRight',
+    'reject',
+    'rest',
+    'result',
+    'shuffle',
+    'size',
+    'some',
+    'sortBy',
+    'sortedIndex',
+    'toArray',
+    'uniqueId',
+    'value',
+    'without'
+  ];
+
+  /** List of methods used by Underscore */
+  var underscoreMethods = _.without.apply(_, [allMethods].concat([
+    'at',
+    'bindKey',
+    'cloneDeep',
+    'forIn',
+    'forOwn',
+    'isPlainObject',
+    'merge',
+    'partialRight'
+  ]));
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a context object to use with `vm.runInContext`.
+   *
+   * @private
+   * @returns {Object} Returns a new context object.
+   */
+  function createContext() {
+    return vm.createContext({
+      'clearTimeout': clearTimeout,
+      'setTimeout': setTimeout
+    });
+  }
+
+  /**
+   * Expands a list of method names to include real and alias names.
+   *
+   * @private
+   * @param {Array} methodNames The array of method names to expand.
+   * @returns {Array} Returns a new array of expanded method names.
+   */
+  function expandMethodNames(methodNames) {
+    return methodNames.reduce(function(result, methodName) {
+      var realName = getRealName(methodName);
+      result.push.apply(result, [realName].concat(getAliases(realName)));
+      return result;
+    }, []);
+  }
+
+  /**
+   * Gets the aliases associated with a given function name.
+   *
+   * @private
+   * @param {String} funcName The name of the function to get aliases for.
+   * @returns {Array} Returns an array of aliases.
+   */
+  function getAliases(funcName) {
+    return realToAliasMap[funcName] || [];
+  }
+
+  /**
+   * Gets the names of methods belonging to the given `category`.
+   *
+   * @private
+   * @param {String} category The category to filter by.
+   * @returns {Array} Returns a new array of method names belonging to the given category.
+   */
+  function getMethodsByCategory(category) {
+    switch (category) {
+      case 'Arrays':
+        return arraysMethods.slice();
+      case 'Chaining':
+        return chainingMethods.slice();
+      case 'Collections':
+        return collectionsMethods.slice();
+      case 'Functions':
+        return functionsMethods.slice();
+      case 'Objects':
+        return objectsMethods.slice();
+      case 'Utilities':
+        return utilityMethods.slice();
+    }
+    return [];
+  }
+
+  /**
+   * Gets the real name, not alias, of a given function name.
+   *
+   * @private
+   * @param {String} funcName The name of the function to resolve.
+   * @returns {String} Returns the real name.
+   */
+  function getRealName(funcName) {
+    return aliasToRealMap[funcName] || funcName;
+  }
+
+  /**
+   * Tests if a given method on the `lodash` object can be called successfully.
+   *
+   * @private
+   * @param {Object} lodash The built Lo-Dash object.
+   * @param {String} methodName The name of the Lo-Dash method to test.
+   * @param {String} message The unit test message.
+   */
+  function testMethod(lodash, methodName, message) {
+    var pass = true,
+        array = [['a', 1], ['b', 2], ['c', 3]],
+        object = { 'a': 1, 'b': 2, 'c': 3 },
+        noop = function() {},
+        string = 'abc',
+        template = '<%= a %>',
+        func = lodash[methodName];
+
+    try {
+      if (arraysMethods.indexOf(methodName) > -1) {
+        if (/(?:indexOf|sortedIndex|without)$/i.test(methodName)) {
+          func(array, string);
+        } else if (/^(?:difference|intersection|union|uniq|zip)/.test(methodName)) {
+          func(array, array);
+        } else if (methodName == 'range') {
+          func(2, 4);
+        } else {
+          func(array);
+        }
+      }
+      else if (chainingMethods.indexOf(methodName) > -1) {
+        if (methodName == 'chain') {
+          lodash.chain(array);
+          lodash(array).chain();
+        }
+        else if (methodName == 'mixin') {
+          lodash.mixin({});
+        }
+        else {
+          lodash(array)[methodName](noop);
+        }
+      }
+      else if (collectionsMethods.indexOf(methodName) > -1) {
+        if (/^(?:count|group|sort)By$/.test(methodName)) {
+          func(array, noop);
+          func(array, string);
+          func(object, noop);
+          func(object, string);
+        }
+        else if (/^(?:size|toArray)$/.test(methodName)) {
+          func(array);
+          func(object);
+        }
+        else if (methodName == 'at') {
+          func(array, 0, 2);
+          func(object, 'a', 'c');
+        }
+        else if (methodName == 'invoke') {
+          func(array, 'slice');
+          func(object, 'toFixed');
+        }
+        else if (methodName == 'where') {
+          func(array, object);
+          func(object, object);
+        }
+        else {
+          func(array, noop, object);
+          func(object, noop, object);
+        }
+      }
+      else if (functionsMethods.indexOf(methodName) > -1) {
+        if (methodName == 'after') {
+          func(1, noop);
+        } else if (methodName == 'bindAll') {
+          func({ 'noop': noop });
+        } else if (methodName == 'bindKey') {
+          func(lodash, 'identity', array, string);
+        } else if (/^(?:bind|partial(?:Right)?)$/.test(methodName)) {
+          func(noop, object, array, string);
+        } else if (/^(?:compose|memoize|wrap)$/.test(methodName)) {
+          func(noop, noop);
+        } else if (/^(?:debounce|throttle)$/.test(methodName)) {
+          func(noop, 100);
+        } else {
+          func(noop);
+        }
+      }
+      else if (objectsMethods.indexOf(methodName) > -1) {
+        if (methodName == 'clone') {
+          func(object);
+          func(object, true);
+        }
+        else if (/^(?:defaults|extend|merge)$/.test(methodName)) {
+          func({}, object);
+        } else if (/^(?:forIn|forOwn)$/.test(methodName)) {
+          func(object, noop);
+        } else if (/^(?:omit|pick)$/.test(methodName)) {
+          func(object, 'b');
+        } else if (methodName == 'has') {
+          func(object, string);
+        } else {
+          func(object);
+        }
+      }
+      else if (utilityMethods.indexOf(methodName) > -1) {
+        if (methodName == 'result') {
+          func(object, 'b');
+        } else if (methodName == 'template') {
+          func(template, object);
+          func(template, null, { 'imports': object })(object);
+        } else if (methodName == 'times') {
+          func(2, noop, object);
+        } else {
+          func(string, object);
+        }
+      }
+    }
+    catch(e) {
+      console.log(e);
+      pass = false;
+    }
+    ok(pass, '_.' + methodName + ': ' + message);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('minified AMD snippet');
+
+  (function() {
+    var start = _.once(QUnit.start);
+
+    asyncTest('`lodash`', function() {
+      build(['-s'], function(data) {
+        // used by r.js build optimizer
+        var defineHasRegExp = /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
+            basename = path.basename(data.outputPath, '.js');
+
+        ok(!!defineHasRegExp.exec(data.source), basename);
+        start();
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('template builds');
+
+  (function() {
+    var templatePath = __dirname + '/template';
+
+    asyncTest('`lodash template=*.jst`', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'template=' + templatePath + '/*.jst'], function(data) {
+        var basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        var object = {
+          'a': { 'people': ['moe', 'larry', 'curly'] },
+          'b': { 'epithet': 'stooge' },
+          'c': { 'name': 'ES6' }
+        };
+
+        context._ = _;
+        vm.runInContext(data.source, context);
+
+        equal(_.templates.a(object.a).replace(/[\r\n]+/g, ''), '<ul><li>moe</li><li>larry</li><li>curly</li></ul>', basename);
+        equal(_.templates.b(object.b), 'Hello stooge.', basename);
+        equal(_.templates.c(object.c), 'Hello ES6!', basename);
+        delete _.templates;
+        start();
+      });
+    });
+
+    var commands = [
+      '',
+      'moduleId=underscore'
+    ];
+
+    commands.forEach(function(command) {
+      var expectedId = /underscore/.test(command) ? 'underscore' : 'lodash';
+
+      asyncTest('`lodash template=*.jst exports=amd' + (command ? ' ' + command : '') + '`', function() {
+        var start = _.after(2, _.once(QUnit.start));
+
+        build(['-s', 'template=' + templatePath + '/*.jst', 'exports=amd'].concat(command || []), function(data) {
+          var moduleId,
+              basename = path.basename(data.outputPath, '.js'),
+              context = createContext();
+
+          context.define = function(requires, factory) {
+            factory(_);
+            moduleId = requires[0];
+          };
+
+          context.define.amd = {};
+          vm.runInContext(data.source, context);
+
+          equal(moduleId, expectedId, basename);
+          ok('a' in _.templates && 'b' in _.templates, basename);
+          equal(_.templates.a({ 'people': ['moe', 'larry'] }), '<ul>\n<li>moe</li><li>larry</li>\n</ul>', basename);
+
+          delete _.templates;
+          start();
+        });
+      });
+
+      asyncTest('`lodash settings=...' + (command ? ' ' + command : '') + '`', function() {
+        var start = _.after(2, _.once(QUnit.start));
+
+        build(['-s', 'template=' + templatePath + '/*.tpl', 'settings={interpolate:/{{([\\s\\S]+?)}}/}'].concat(command || []), function(data) {
+          var moduleId,
+              basename = path.basename(data.outputPath, '.js'),
+              context = createContext();
+
+          var object = {
+            'd': { 'name': 'Mustache' }
+          };
+
+          context.define = function(requires, factory) {
+            factory(_);
+            moduleId = requires[0];
+          };
+
+          context.define.amd = {};
+          vm.runInContext(data.source, context);
+
+          equal(moduleId, expectedId, basename);
+          equal(_.templates.d(object.d), 'Hello Mustache!', basename);
+          delete _.templates;
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('independent builds');
+
+  (function() {
+    var reCustom = /Custom Build/,
+        reLicense = /^\/\**\s+\* @license[\s\S]+?\*\/\n/;
+
+    asyncTest('debug only', function() {
+      var start = _.once(QUnit.start);
+      build(['-d', '-s'], function(data) {
+        equal(path.basename(data.outputPath, '.js'), 'lodash');
+        start();
+      });
+    });
+
+    asyncTest('debug custom', function() {
+      var start = _.once(QUnit.start);
+      build(['-d', '-s', 'backbone'], function(data) {
+        equal(path.basename(data.outputPath, '.js'), 'lodash.custom');
+
+        var comment = data.source.match(reLicense);
+        ok(reCustom.test(comment));
+        start();
+      });
+    });
+
+    asyncTest('minified only', function() {
+      var start = _.once(QUnit.start);
+      build(['-m', '-s'], function(data) {
+        equal(path.basename(data.outputPath, '.js'), 'lodash.min');
+        start();
+      });
+    });
+
+    asyncTest('minified custom', function() {
+      var start = _.once(QUnit.start);
+      build(['-m', '-s', 'backbone'], function(data) {
+        equal(path.basename(data.outputPath, '.js'), 'lodash.custom.min');
+
+        var comment = data.source.match(reLicense);
+        ok(reCustom.test(comment));
+        start();
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('source maps');
+
+  (function() {
+    var mapCommands = [
+      '-p',
+      '-p custom.map',
+      '--source-map',
+      '--source-map custom.map'
+    ];
+
+    var outputCommands = [
+      '',
+      '-o foo.js',
+      '-m -o bar.js'
+    ];
+
+    mapCommands.forEach(function(mapCommand) {
+      outputCommands.forEach(function(outputCommand) {
+        asyncTest('`lodash ' + mapCommand + (outputCommand ? ' ' + outputCommand : '') + '`', function() {
+          var callback = _.once(function(data) {
+            var basename = path.basename(data.outputPath, '.js'),
+                comment = (/(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)$/.exec(data.source) || [])[0],
+                sources = /foo.js/.test(outputCommand) ? ['foo.js'] : ['lodash' + (outputCommand.length ? '' : '.custom') + '.js'],
+                sourceMap = JSON.parse(data.sourceMap),
+                sourceMapURL = (/\w+(?=\.map$)/.exec(mapCommand) || [basename])[0];
+
+            ok(RegExp('/\\*\\n//@ sourceMappingURL=' + sourceMapURL + '.map\\n\\*/').test(comment), basename);
+            equal(sourceMap.file, basename + '.js', basename);
+            deepEqual(sourceMap.sources, sources, basename);
+
+            QUnit.start();
+          });
+
+          outputCommand = outputCommand ? outputCommand.split(' ') : [];
+          if (outputCommand.indexOf('-m') < 0) {
+            callback = _.after(2, callback);
+          }
+          build(['-s'].concat(mapCommand.split(' '), outputCommand), callback);
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('strict modifier');
+
+  (function() {
+    var object = Object.freeze({
+      'a': _.identity,
+      'b': undefined
+    });
+
+    var modes = [
+      'non-strict',
+      'strict'
+    ];
+
+    modes.forEach(function(strictMode, index) {
+      asyncTest(strictMode + ' should ' + (index ? 'error': 'silently fail') + ' attempting to overwrite read-only properties', function() {
+        var commands = ['-s', 'include=bindAll,defaults,extend'],
+            start = _.after(2, _.once(QUnit.start));
+
+        if (index) {
+          commands.push('strict');
+        }
+        build(commands, function(data) {
+          var basename = path.basename(data.outputPath, '.js'),
+              context = createContext();
+
+          vm.runInContext(data.source, context);
+          var lodash = context._;
+
+          var actual = _.every([
+            function() { lodash.bindAll(object); },
+            function() { lodash.extend(object, { 'a': 1 }); },
+            function() { lodash.defaults(object, { 'b': 2 }); }
+          ], function(fn) {
+            var pass = !index;
+            try {
+              fn();
+            } catch(e) {
+              pass = !!index;
+            }
+            return pass;
+          });
+
+          ok(actual, basename);
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('underscore chaining methods');
+
+  (function() {
+    var commands = [
+      'backbone',
+      'underscore'
+    ];
+
+    commands.forEach(function(command) {
+      asyncTest('`lodash ' + command +'`', function() {
+        var start = _.after(2, _.once(QUnit.start));
+
+        build(['-s', command], function(data) {
+          var basename = path.basename(data.outputPath, '.js'),
+              context = createContext();
+
+          vm.runInContext(data.source, context);
+          var lodash = context._;
+
+          ok(lodash.chain(1) instanceof lodash, '_.chain: ' + basename);
+          ok(lodash(1).chain() instanceof lodash, '_#chain: ' + basename);
+
+          var wrapped = lodash(1);
+          strictEqual(wrapped.identity(), 1, '_(...) wrapped values are not chainable by default: ' + basename);
+          equal(String(wrapped) === '1', false, '_#toString should not be implemented: ' + basename);
+          equal(Number(wrapped) === 1 , false, '_#valueOf should not be implemented: ' + basename);
+
+          wrapped.chain();
+          ok(wrapped.has('x') instanceof lodash, '_#has returns wrapped values when chaining: ' + basename);
+          ok(wrapped.join() instanceof lodash, '_#join returns wrapped values when chaining: ' + basename);
+
+          wrapped = lodash([1, 2, 3]);
+          ok(wrapped.pop() instanceof lodash, '_#pop returns wrapped values: ' + basename);
+          ok(wrapped.shift() instanceof lodash, '_#shift returns wrapped values: ' + basename);
+          deepEqual(wrapped.splice(0, 0).value(), [2], '_#splice returns wrapper: ' + basename);
+
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('underscore modifier');
+
+  (function() {
+    asyncTest('modified methods should work correctly', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'underscore'], function(data) {
+        var last,
+            array = [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }],
+            basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        vm.runInContext(data.source, context);
+        var lodash = context._;
+
+        var object = {
+          'fn': lodash.bind(function(foo) {
+            return foo + this.bar;
+          }, { 'bar': 1 }, 1)
+        };
+
+        equal(object.fn(), 2, '_.bind: ' + basename);
+
+        var actual = lodash.clone('a', function() {
+          return this.a;
+        }, { 'a': 'A' });
+
+        equal(actual, 'a', '_.clone should ignore `callback` and `thisArg`: ' + basename);
+        strictEqual(lodash.clone(array, true)[0], array[0], '_.clone should ignore `deep`: ' + basename);
+
+        strictEqual(lodash.contains({ 'a': 1, 'b': 2 }, 1), true, '_.contains should work with objects: ' + basename);
+        strictEqual(lodash.contains([1, 2, 3], 1, 2), true, '_.contains should ignore `fromIndex`: ' + basename);
+        strictEqual(lodash.every([true, false, true]), false, '_.every: ' + basename);
+
+        function Foo() {}
+        Foo.prototype = { 'a': 1 };
+
+        actual = lodash.defaults({ 'a': null }, { 'a': 1 });
+        strictEqual(actual.a, 1, '_.defaults should overwrite `null` values: ' + basename);
+
+        deepEqual(lodash.defaults({}, new Foo), Foo.prototype, '_.defaults should assign inherited `source` properties: ' + basename);
+        deepEqual(lodash.extend({}, new Foo), Foo.prototype, '_.extend should assign inherited `source` properties: ' + basename);
+
+        actual = lodash.extend({}, { 'a': 0 }, function(a, b) {
+          return this[b];
+        }, [2]);
+
+        strictEqual(actual.a, 0, '_.extend should ignore `callback` and `thisArg`: ' + basename);
+
+        actual = lodash.find(array, function(value) {
+          return 'a' in value;
+        });
+
+        equal(actual, _.first(array), '_.find: ' + basename);
+
+        actual = lodash.forEach(array, function(value) {
+          last = value;
+          return false;
+        });
+
+        equal(last, _.last(array), '_.forEach should not exit early: ' + basename);
+        equal(actual, undefined, '_.forEach should return `undefined`: ' + basename);
+
+        object = { 'length': 0, 'splice': Array.prototype.splice };
+        equal(lodash.isEmpty(object), false, '_.isEmpty should return `false` for jQuery/MooTools DOM query collections: ' + basename);
+
+        object = { 'a': 1, 'b': 2, 'c': 3 };
+        equal(lodash.isEqual(object, { 'a': 1, 'b': 0, 'c': 3 }), false, '_.isEqual: ' + basename);
+
+        actual = lodash.isEqual('a', 'b', function(a, b) {
+          return this[a] == this[b];
+        }, { 'a': 1, 'b': 1 });
+
+        strictEqual(actual, false, '_.isEqual should ignore `callback` and `thisArg`: ' + basename);
+
+        equal(lodash.max('abc'), -Infinity, '_.max should return `-Infinity` for strings: ' + basename);
+        equal(lodash.min('abc'), Infinity, '_.min should return `Infinity` for strings: ' + basename);
+
+        // avoid issues comparing objects with `deepEqual`
+        object = { 'a': 1, 'b': 2, 'c': 3 };
+        actual = lodash.omit(object, function(value) { return value == 3; });
+        deepEqual(_.keys(actual).sort(), ['a', 'b', 'c'], '_.omit should not accept a `callback`: ' + basename);
+
+        actual = lodash.pick(object, function(value) { return value != 3; });
+        deepEqual(_.keys(actual), [], '_.pick should not accept a `callback`: ' + basename);
+
+        strictEqual(lodash.result(), null, '_.result should return `null` for falsey `object` arguments: ' + basename);
+        strictEqual(lodash.some([false, true, false]), true, '_.some: ' + basename);
+        equal(lodash.template('${a}', object), '${a}', '_.template should ignore ES6 delimiters: ' + basename);
+        equal('imports' in lodash.templateSettings, false, '_.templateSettings should not have an "imports" property: ' + basename);
+        strictEqual(lodash.uniqueId(0), '1', '_.uniqueId should ignore a prefix of `0`: ' + basename);
+
+        var collection = [{ 'a': { 'b': 1, 'c': 2 } }];
+        deepEqual(lodash.where(collection, { 'a': { 'b': 1 } }), [], '_.where performs shallow comparisons: ' + basename);
+
+        collection = [{ 'a': 1 }, { 'a': 1 }];
+        deepEqual(lodash.where(collection, { 'a': 1 }, true), collection[0], '_.where supports a `first` argument: ' + basename);
+        deepEqual(lodash.where(collection, {}, true), null, '_.where should return `null` when passed `first` and falsey `properties`: ' + basename);
+
+        deepEqual(lodash.findWhere(collection, { 'a': 1 }), collection[0], '_.findWhere: ' + basename);
+        strictEqual(lodash.findWhere(collection, {}), null, '_.findWhere should return `null` for falsey `properties`: ' + basename);
+
+        start();
+      });
+    });
+
+    asyncTest('should not have any Lo-Dash-only methods', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'underscore'], function(data) {
+        var basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        vm.runInContext(data.source, context);
+        var lodash = context._;
+
+        _.each([
+          'assign',
+          'at',
+          'bindKey',
+          'forIn',
+          'forOwn',
+          'isPlainObject',
+          'merge',
+          'partialRight'
+        ], function(methodName) {
+          equal(lodash[methodName], undefined, '_.' + methodName + ' should not exist: ' + basename);
+        });
+
+        start();
+      });
+    });
+
+    asyncTest('`lodash underscore include=findWhere`', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'underscore', 'include=findWhere'], function(data) {
+        var basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        vm.runInContext(data.source, context);
+        var lodash = context._;
+
+        var collection = [{ 'a': 1 }, { 'a': 1 }];
+        deepEqual(lodash.findWhere(collection, { 'a': 1 }), collection[0], '_.findWhere: ' + basename);
+
+        start();
+      });
+    });
+
+    asyncTest('`lodash underscore include=partial`', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'underscore', 'include=partial'], function(data) {
+        var basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        vm.runInContext(data.source, context);
+        var lodash = context._;
+
+        equal(lodash.partial(_.identity, 2)(), 2, '_.partial: ' + basename);
+        start();
+      });
+    });
+
+    asyncTest('`lodash underscore plus=clone`', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'underscore', 'plus=clone'], function(data) {
+        var array = [{ 'value': 1 }],
+            basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        vm.runInContext(data.source, context);
+        var lodash = context._,
+            clone = lodash.clone(array, true);
+
+        ok(_.isEqual(array, clone), basename);
+        notEqual(array[0], clone[0], basename);
+        start();
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('exports command');
+
+  (function() {
+    var commands = [
+      'exports=amd',
+      'exports=commonjs',
+      'exports=global',
+      'exports=node',
+      'exports=none'
+    ];
+
+    commands.forEach(function(command, index) {
+      asyncTest('`lodash ' + command +'`', function() {
+        var start = _.after(2, _.once(QUnit.start));
+
+        build(['-s', command], function(data) {
+          var basename = path.basename(data.outputPath, '.js'),
+              context = createContext(),
+              pass = false,
+              source = data.source;
+
+          switch(index) {
+            case 0:
+              context.define = function(fn) {
+                pass = true;
+                context._ = fn();
+              };
+              context.define.amd = {};
+              vm.runInContext(source, context);
+              ok(pass, basename);
+              break;
+
+            case 1:
+              context.exports = {};
+              vm.runInContext(source, context);
+              ok(_.isFunction(context.exports._), basename);
+              strictEqual(context._, undefined, basename);
+              break;
+
+            case 2:
+              vm.runInContext(source, context);
+              ok(_.isFunction(context._), basename);
+              break;
+
+            case 3:
+              context.exports = {};
+              context.module = { 'exports': context.exports };
+              vm.runInContext(source, context);
+              ok(_.isFunction(context.module.exports), basename);
+              strictEqual(context._, undefined, basename);
+              break;
+
+            case 4:
+              vm.runInContext(source, context);
+              strictEqual(context._, undefined, basename);
+          }
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('iife command');
+
+  (function() {
+    var commands = [
+      'iife=this["lodash"]=(function(window,undefined){%output%;return lodash}(this))',
+      'iife=define(function(window,undefined){return function(){%output%;return lodash}}(this));'
+    ];
+
+    commands.forEach(function(command) {
+      asyncTest('`lodash ' + command +'`', function() {
+        var start = _.after(2, _.once(QUnit.start));
+
+        build(['-s', 'exports=none', command], function(data) {
+          var basename = path.basename(data.outputPath, '.js'),
+              context = createContext();
+
+          context.define = function(func) {
+            context.lodash = func();
+          };
+
+          try {
+            vm.runInContext(data.source, context);
+          } catch(e) {
+            console.log(e);
+          }
+
+          var lodash = context.lodash || {};
+          ok(_.isString(lodash.VERSION), basename);
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('output options');
+
+  (function() {
+    var commands = [
+      '-o a.js',
+      '--output a.js'
+    ];
+
+    commands.forEach(function(command, index) {
+      asyncTest('`lodash ' + command +'`', function() {
+        var counter = -1,
+            start = _.after(2, _.once(QUnit.start));
+
+        build(['-s'].concat(command.split(' ')), function(data) {
+          equal(path.basename(data.outputPath, '.js'), (++counter ? 'a.min' : 'a'), command);
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('stdout options');
+
+  (function() {
+    var commands = [
+      '-c',
+      '-c -d',
+      '--stdout',
+    ];
+
+    commands.forEach(function(command, index) {
+      asyncTest('`lodash ' + command +'`', function() {
+        var written,
+            start = _.once(QUnit.start),
+            write = process.stdout.write;
+
+        process.stdout.write = function(string) {
+          written = string;
+        };
+
+        build(['exports=', 'include='].concat(command.split(' ')), function(data) {
+          process.stdout.write = write;
+          equal(written, data.source);
+          equal(arguments.length, 1);
+          start();
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('mobile build');
+
+  (function() {
+    asyncTest('`lodash mobile`', function() {
+      var start = _.after(2, _.once(QUnit.start));
+
+      build(['-s', 'mobile'], function(data) {
+        var basename = path.basename(data.outputPath, '.js'),
+            context = createContext();
+
+        try {
+          vm.runInContext(data.source, context);
+        } catch(e) {
+          console.log(e);
+        }
+
+        var array = [1, 2, 3],
+            object1 = [{ 'a': 1 }],
+            object2 = [{ 'b': 2 }],
+            object3 = [{ 'a': 1, 'b': 2 }],
+            circular1 = { 'a': 1 },
+            circular2 = { 'a': 1 },
+            lodash = context._;
+
+        circular1.b = circular1;
+        circular2.b = circular2;
+
+        deepEqual(lodash.merge(object1, object2), object3, basename);
+        deepEqual(lodash.sortBy([3, 2, 1], _.identity), array, basename);
+        strictEqual(lodash.isEqual(circular1, circular2), true, basename);
+
+        var actual = lodash.cloneDeep(circular1);
+        ok(actual != circular1 && actual.b == actual, basename);
+        start();
+      });
+    });
+
+    asyncTest('`lodash csp`', function() {
+      var sources = [];
+
+      var check = _.after(2, _.once(function() {
+        equal(sources[0], sources[1]);
+        QUnit.start();
+      }));
+
+      var callback = function(data) {
+        // remove copyright header and append source
+        sources.push(data.source.replace(/^\/\**[\s\S]+?\*\/\n/, ''));
+        check();
+      };
+
+      build(['-s', '-d', 'csp'], callback);
+      build(['-s', '-d', 'mobile'], callback);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash build');
+
+  (function() {
+    var commands = [
+      'backbone',
+      'csp',
+      'legacy',
+      'mobile',
+      'modern',
+      'strict',
+      'underscore',
+      'category=arrays',
+      'category=chaining',
+      'category=collections',
+      'category=functions',
+      'category=objects',
+      'category=utilities',
+      'exclude=union,uniq,zip',
+      'include=each,filter,map',
+      'include=once plus=bind,Chaining',
+      'category=collections,functions',
+      'backbone legacy category=utilities minus=first,last',
+      'legacy include=defer',
+      'legacy underscore',
+      'underscore include=debounce,throttle plus=after minus=throttle',
+      'underscore mobile strict category=functions exports=amd,global plus=pick,uniq',
+    ]
+    .concat(
+      allMethods.map(function(methodName) {
+        return 'include=' + methodName;
+      })
+    );
+
+    commands.forEach(function(origCommand) {
+      _.times(4, function(index) {
+        var command = origCommand;
+
+        if (index == 1) {
+          if (/legacy|mobile/.test(command)) {
+            return;
+          }
+          command = 'mobile ' + command;
+        }
+        if (index == 2) {
+          if (/legacy|modern/.test(command)) {
+            return;
+          }
+          command = 'modern ' + command;
+        }
+        if (index == 3) {
+          if (/category|legacy|underscore/.test(command)) {
+            return;
+          }
+          command = 'underscore ' + command;
+        }
+        asyncTest('`lodash ' + command +'`', function() {
+          var start = _.after(2, _.once(QUnit.start));
+
+          build(['--silent'].concat(command.split(' ')), function(data) {
+            var methodNames,
+                basename = path.basename(data.outputPath, '.js'),
+                context = createContext(),
+                isUnderscore = /backbone|underscore/.test(command),
+                exposeAssign = !isUnderscore;
+
+            try {
+              vm.runInContext(data.source, context);
+            } catch(e) {
+              console.log(e);
+            }
+            // add method names explicitly
+            if (/include/.test(command)) {
+              methodNames = command.match(/include=(\S*)/)[1].split(/, */);
+            }
+            // add method names required by Backbone and Underscore builds
+            if (/backbone/.test(command) && !methodNames) {
+              methodNames = backboneDependencies.slice();
+            }
+            if (isUnderscore) {
+              if (methodNames) {
+                exposeAssign = methodNames.indexOf('assign') > -1;
+              } else {
+                methodNames = underscoreMethods.slice();
+              }
+            }
+            // add method names explicitly by category
+            if (/category/.test(command)) {
+              // resolve method names belonging to each category (case-insensitive)
+              methodNames = command.match(/category=(\S*)/)[1].split(/, */).reduce(function(result, category) {
+                var capitalized = category[0].toUpperCase() + category.toLowerCase().slice(1);
+                return result.concat(getMethodsByCategory(capitalized));
+              }, methodNames || []);
+            }
+            // init `methodNames` if it hasn't been inited
+            if (!methodNames) {
+              methodNames = allMethods.slice();
+            }
+            if (/plus/.test(command)) {
+              methodNames = methodNames.concat(command.match(/plus=(\S*)/)[1].split(/, */));
+            }
+            if (/minus/.test(command)) {
+              methodNames = _.without.apply(_, [methodNames]
+                .concat(expandMethodNames(command.match(/minus=(\S*)/)[1].split(/, */))));
+            }
+            if (/exclude/.test(command)) {
+              methodNames = _.without.apply(_, [methodNames]
+                .concat(expandMethodNames(command.match(/exclude=(\S*)/)[1].split(/, */))));
+            }
+
+            // expand aliases and categories to real method names
+            methodNames = expandMethodNames(methodNames).reduce(function(result, methodName) {
+              return result.concat(methodName, getMethodsByCategory(methodName));
+            }, []);
+
+            // remove nonexistent and duplicate method names
+            methodNames = _.uniq(_.intersection(allMethods, expandMethodNames(methodNames)));
+
+            if (!exposeAssign) {
+              methodNames = _.without(methodNames, 'assign');
+            }
+            var lodash = context._ || {};
+            methodNames.forEach(function(methodName) {
+              testMethod(lodash, methodName, basename);
+            });
+
+            start();
+          });
+        });
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  if (timeLimit > 0) {
+    setTimeout(function() {
+      process.exit(QUnit.config.stats.bad ? 1 : 0);
+    }, timeLimit);
+  }
+  // explicitly call `QUnit.start()` for Narwhal, Node.js, Rhino, and RingoJS
+  if (!global.document) {
+    QUnit.start();
+  }
+}());
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test.js	(revision 533)
@@ -0,0 +1,2920 @@
+;(function(window, undefined) {
+  'use strict';
+
+  /** Use a single "load" function */
+  var load = typeof require == 'function' ? require : window.load;
+
+  /** The file path of the Lo-Dash file to test */
+  var filePath = (function() {
+    var min = 0;
+    var result = window.phantom
+      ? phantom.args
+      : (window.system
+          ? (min = 1, system.args)
+          : (window.process ? (min = 2, process.argv) : (window.arguments || []))
+        );
+
+    var last = result[result.length - 1];
+    result = (result.length > min && last != 'test.js') ? last : '../lodash.js';
+
+    try {
+      result = require('fs').realpathSync(result);
+    } catch(e) { }
+
+    return result;
+  }());
+
+  /** The basename of the Lo-Dash file to test */
+  var basename = /[\w.-]+$/.exec(filePath)[0];
+
+  /** The `platform` object to check */
+  var platform =
+    window.platform ||
+    load('../vendor/platform.js/platform.js') ||
+    window.platform;
+
+  /** The unit testing framework */
+  var QUnit =
+    window.QUnit || (
+      window.addEventListener || (window.addEventListener = Function.prototype),
+      window.setTimeout || (window.setTimeout = Function.prototype),
+      window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit,
+      load('../vendor/qunit-clib/qunit-clib.js'),
+      window.addEventListener === Function.prototype && delete window.addEventListener,
+      window.QUnit
+    );
+
+  /** The `lodash` function to test */
+  var _ = window._ || (
+    _ = load(filePath) || window._,
+    _._ || _
+  );
+
+  /** Used to pass falsey values to methods */
+  var falsey = [
+    ,
+    '',
+    0,
+    false,
+    NaN,
+    null,
+    undefined
+  ];
+
+  /** Shortcut used to make object properties immutable */
+  var freeze = Object.freeze;
+
+  /** Used to set property descriptors */
+  var setDescriptor = (function(fn) {
+    try {
+      var o = {};
+      return fn(o, o, o) && fn;
+    } catch(e) { }
+  }(Object.defineProperty));
+
+  /** Shortcut used to convert array-like objects to arrays */
+  var slice = [].slice;
+
+  /** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */
+  var shadowed = {
+    'constructor': 1,
+    'hasOwnProperty': 2,
+    'isPrototypeOf': 3,
+    'propertyIsEnumerable': 4,
+    'toLocaleString': 5,
+    'toString': 6,
+    'valueOf': 7
+  };
+
+  /** Used to check problem JScript properties too */
+  var shadowedKeys = [
+    'constructor',
+    'hasOwnProperty',
+    'isPrototypeOf',
+    'propertyIsEnumerable',
+    'toLocaleString',
+    'toString',
+    'valueOf'
+  ];
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Skips a given number of tests with a passing result.
+   *
+   * @private
+   * @param {Number} [count=1] The number of tests to skip.
+   */
+  function skipTest(count) {
+    count || (count = 1);
+    while (count--) {
+      ok(true, 'test skipped');
+    }
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // add object from iframe
+  (function() {
+    if (!window.document || window.phantom) {
+      return;
+    }
+    var body = document.body,
+        iframe = document.createElement('iframe');
+
+    iframe.frameBorder = iframe.height = iframe.width = 0;
+    body.appendChild(iframe);
+    var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc;
+    idoc.write("<script>parent._._object = { 'a': 1, 'b': 2, 'c': 3 };<\/script>");
+    idoc.close();
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  // explicitly call `QUnit.module()` instead of `module()`
+  // in case we are in a CLI environment
+  QUnit.module(basename);
+
+  (function() {
+    test('supports loading ' + basename + ' as the "lodash" module', function() {
+      if (window.define && define.amd) {
+        equal((lodashModule || {}).moduleName, 'lodash');
+      } else {
+        skipTest();
+      }
+    });
+
+    test('supports loading ' + basename + ' with the Require.js "shim" configuration option', function() {
+      if (window.define && define.amd) {
+        equal((shimmedModule || {}).moduleName, 'shimmed');
+      } else {
+        skipTest();
+      }
+    });
+
+    test('supports loading ' + basename + ' as the "underscore" module', function() {
+      if (window.define && define.amd) {
+        equal((underscoreModule || {}).moduleName, 'underscore');
+      } else {
+        skipTest();
+      }
+    });
+
+    test('avoids overwritten native methods', function() {
+      if (window.document && !window.phantom) {
+        notDeepEqual(lodashBadShim.keys({ 'a': 1 }), []);
+      } else {
+        skipTest();
+      }
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash constructor');
+
+  (function() {
+    test('creates a new instance when called without the `new` operator', function() {
+      ok(_() instanceof _);
+    });
+
+    test('should return passed LoDash instances', function() {
+      var wrapped = _([]);
+      equal(_(wrapped), wrapped);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.assign');
+
+  (function() {
+    test('should not error on `null` or `undefined` sources (test in IE < 9)', function() {
+      try {
+        deepEqual(_.assign({}, null, undefined, { 'a': 1 }), { 'a': 1 });
+      } catch(e) {
+        ok(false);
+      }
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.at');
+
+  (function() {
+    test('should return `undefined` for nonexistent keys', function() {
+      var actual = _.at(['a', 'b',  'c'], [0, 2, 4]);
+      deepEqual(actual, ['a', 'c', undefined]);
+    });
+
+    test('should return an empty array when no keys are passed', function() {
+      deepEqual(_.at(['a', 'b', 'c']), []);
+    });
+
+    test('should accept multiple key arguments', function() {
+      var actual = _.at(['a', 'b', 'c', 'd'], 0, 2, 3);
+      deepEqual(actual, ['a', 'c', 'd']);
+    });
+
+    test('should work with an object for `collection`', function() {
+      var actual = _.at({ 'a': 1, 'b': 2, 'c': 3 }, ['a', 'c']);
+      deepEqual(actual, [1, 3]);
+    });
+
+    _.each({
+      'literal': 'abc',
+      'object': Object('abc')
+    },
+    function(collection, key) {
+      test('should work with a string ' + key + ' for `collection`', function() {
+        deepEqual(_.at(collection, [0, 2]), ['a', 'c']);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.bind');
+
+  (function() {
+    test('should append array arguments to partially applied arguments (test in IE < 9)', function() {
+      var args,
+          bound = _.bind(function() { args = slice.call(arguments); }, {}, 'a');
+
+      bound(['b'], 'c');
+      deepEqual(args, ['a', ['b'], 'c']);
+    });
+
+    test('ensure `new bound` is an instance of `func`', function() {
+      var func = function() {},
+          bound = _.bind(func, {});
+
+      ok(new bound instanceof func);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.bindAll');
+
+  (function() {
+    test('should bind all methods of `object`', function() {
+      function Foo() {
+        this._a = 1;
+        this._b = 2;
+        this.a = function() { return this._a; };
+      };
+
+      Foo.prototype.b = function() {return this._b; };
+
+      var object = new Foo;
+      _.bindAll(object);
+
+      var actual = _.map(_.functions(object), function(methodName) {
+        return object[methodName].call({});
+      });
+
+      deepEqual(actual, [1, 2]);
+    });
+
+    test('should accept arrays of method names', function() {
+      var object = {
+        '_a': 1,
+        '_b': 2,
+        '_c': 3,
+        '_d': 4,
+        'a': function() { return this._a; },
+        'b': function() { return this._b; },
+        'c': function() { return this._c; },
+        'd': function() { return this._d; }
+      };
+
+      _.bindAll(object, ['a', 'b'], ['c']);
+
+      var actual = _.map(_.functions(object), function(methodName) {
+        return object[methodName].call({});
+      });
+
+      deepEqual(actual, [1, 2, 3, undefined]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.bindKey');
+
+  (function() {
+    test('should work when the target function is overwritten', function() {
+      var object = {
+        'name': 'moe',
+        'greet': function(greeting) {
+          return greeting + ': ' + this.name;
+        }
+      };
+
+      var func = _.bindKey(object, 'greet', 'hi');
+      equal(func(), 'hi: moe');
+
+      object.greet = function(greeting) {
+        return greeting + ' ' + this.name + '!';
+      };
+      equal(func(), 'hi moe!');
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('cloning');
+
+  (function() {
+    function Klass() { this.a = 1; }
+    Klass.prototype = { 'b': 1 };
+
+    var nonCloneable = {
+      'an element': window.document && document.body,
+      'a function': Klass
+    };
+
+    var objects = {
+      'an arguments object': arguments,
+      'an array': ['a', 'b', 'c', ''],
+      'an array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 5 },
+      'boolean': false,
+      'boolean object': Object(false),
+      'a Klass instance': new Klass,
+      'an object': { 'a': 0, 'b': 1, 'c': 3 },
+      'an object with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } },
+      'an object from another document': _._object || {},
+      'null': null,
+      'a number': 3,
+      'a number object': Object(3),
+      'a regexp': /a/gim,
+      'a string': 'a',
+      'a string object': Object('a'),
+      'undefined': undefined
+    };
+
+    objects['an array'].length = 5;
+
+    _.forOwn(objects, function(object, key) {
+      test('should deep clone ' + key, function() {
+        var clone = _.cloneDeep(object);
+        strictEqual(_.isEqual(object, clone), true);
+
+        if (_.isObject(object)) {
+          notEqual(clone, object);
+        } else {
+          skipTest();
+        }
+      });
+    });
+
+    _.forOwn(nonCloneable, function(object, key) {
+      test('should not clone ' + key, function() {
+        strictEqual(_.clone(object), object);
+        strictEqual(_.cloneDeep(object), object);
+      });
+    });
+
+    test('should shallow clone when used as `callback` for `_.map`', function() {
+      var expected = [{ 'a': [0] }, { 'b': [1] }],
+          actual = _.map(expected, _.clone);
+
+      ok(actual != expected && actual.a == expected.a && actual.b == expected.b);
+    });
+
+    test('should deep clone `index` and `input` array properties', function() {
+      var array = /x/.exec('x'),
+          actual = _.cloneDeep(array);
+
+      strictEqual(actual.index, 0);
+      equal(actual.input, 'x');
+    });
+
+    test('should deep clone objects with circular references', function() {
+      var object = {
+        'foo': { 'b': { 'foo': { 'c': { } } } },
+        'bar': { }
+      };
+
+      object.foo.b.foo.c = object;
+      object.bar.b = object.foo.b;
+
+      var clone = _.cloneDeep(object);
+      ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object);
+    });
+
+    test('should clone problem JScript properties (test in IE < 9)', function() {
+      deepEqual(_.clone(shadowed), shadowed);
+      notEqual(_.clone(shadowed), shadowed);
+      deepEqual(_.cloneDeep(shadowed), shadowed);
+      notEqual(_.cloneDeep(shadowed), shadowed);
+    });
+
+    _.each([
+      'clone',
+      'cloneDeep'
+    ],
+    function(methodName) {
+      var func = _[methodName],
+          klass = new Klass;
+
+      test('_.' + methodName + ' should pass the correct `callback` arguments', function() {
+        var args;
+
+        func(klass, function() {
+          args || (args = slice.call(arguments));
+        });
+
+        deepEqual(args, [klass]);
+      });
+
+      test('_.' + methodName + ' should correct set the `this` binding', function() {
+        var actual = func('a', function(value) {
+          return this[value];
+        }, { 'a': 'A' });
+
+        equal(actual, 'A');
+      });
+
+      test('_.' + methodName + ' should handle cloning if `callback` returns `undefined`', function() {
+        var actual = _.clone({ 'a': { 'b': 'c' } }, function() { });
+        deepEqual(actual, { 'a': { 'b': 'c' } });
+      });
+    });
+  }(1, 2, 3));
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.contains');
+
+  (function() {
+    _.each({
+      'an array': [1, 2, 3, 1, 2, 3],
+      'an object': { 'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3 },
+      'a string': '123123'
+    },
+    function(collection, key) {
+      test('should work with ' + key + ' and a positive `fromIndex`', function() {
+        strictEqual(_.contains(collection, 1, 2), true);
+      });
+
+      test('should work with ' + key + ' and a `fromIndex` >= collection\'s length', function() {
+        strictEqual(_.contains(collection, 1, 6), false);
+        strictEqual(_.contains(collection, undefined, 6), false);
+        strictEqual(_.contains(collection, 1, 8), false);
+        strictEqual(_.contains(collection, undefined, 8), false);
+      });
+
+      test('should work with ' + key + ' and a negative `fromIndex`', function() {
+        strictEqual(_.contains(collection, 2, -3), true);
+      });
+
+      test('should work with ' + key + ' and a negative `fromIndex` <= negative collection\'s length', function() {
+        strictEqual(_.contains(collection, 1, -6), true);
+        strictEqual(_.contains(collection, 2, -8), true);
+      });
+    });
+
+    _.each({
+      'literal': 'abc',
+      'object': Object('abc')
+    },
+    function(collection, key) {
+      test('should work with a string ' + key + ' for `collection`', function() {
+        strictEqual(_.contains(collection, 'bc'), true);
+        strictEqual(_.contains(collection, 'd'), false);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.countBy');
+
+  (function() {
+    test('should only add values to own, not inherited, properties', function() {
+      var actual = _.countBy([4.2, 6.1, 6.4], function(num) {
+        return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
+      });
+
+      strictEqual(actual.constructor, 1);
+      equal(actual.hasOwnProperty, 2);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.debounce');
+
+  (function() {
+    test('subsequent "immediate" debounced calls return the last `func` result', function() {
+      var debounced = _.debounce(function(value) { return value; }, 32, true),
+          result = [debounced('x'), debounced('y')];
+
+      deepEqual(result, ['x', 'x']);
+    });
+
+    asyncTest('subsequent debounced calls return the last `func` result', function() {
+      var debounced = _.debounce(function(value) { return value; }, 32);
+      debounced('x');
+
+      setTimeout(function() {
+        equal(debounced('y'), 'x');
+        QUnit.start();
+      }, 64);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.defaults');
+
+  (function() {
+    test('should not overwrite `null` values', function() {
+      var actual = _.defaults({ 'a': null }, { 'a': 1 });
+      strictEqual(actual.a, null);
+    });
+
+    test('should overwrite `undefined` values', function() {
+      var actual = _.defaults({ 'a': undefined }, { 'a': 1 });
+      strictEqual(actual.a, 1);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.defer');
+
+  (function() {
+    asyncTest('should accept additional arguments', function() {
+      _.defer(function() {
+        deepEqual(slice.call(arguments), [1, 2, 3]);
+        QUnit.start();
+      }, 1, 2, 3);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.difference');
+
+  (function() {
+    test('should work when using `cachedContains`', function() {
+      var array1 = _.range(27),
+          array2 = array1.slice(),
+          a = {},
+          b = {},
+          c = {};
+
+      array1.push(a, b, c);
+      array2.push(b, c, a);
+
+      deepEqual(_.difference(array1, array2), []);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.escape');
+
+  (function() {
+    test('should not escape the "/" character', function() {
+      equal(_.escape('/'), '/');
+    });
+
+    test('should escape "\'" to "&#39;"', function() {
+      equal(_.escape("'"), "&#39;");
+    });
+
+    test('should return an empty string when passed `null` or `undefined`', function() {
+      equal(_.escape(null), '');
+      equal(_.escape(undefined), '');
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.every');
+
+  (function() {
+    test('should return `false` as soon as the `callback` result is falsey', function() {
+      strictEqual(_.every([true, null, true], _.identity), false);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('source property checks');
+
+  _.each(['assign', 'defaults', 'merge'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should not assign inherited `source` properties', function() {
+      function Foo() {}
+      Foo.prototype = { 'a': 1 };
+      deepEqual(func({}, new Foo), {});
+    });
+
+    test('lodash.' + methodName + ' should treat sparse arrays as dense', function() {
+      var array = Array(3);
+      array[0] = 1;
+      array[2] = 3;
+
+      var actual = func([], array),
+          expected = array.slice();
+
+      expected[1] = undefined;
+
+      ok(1 in actual);
+      deepEqual(actual, expected);
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('strict mode checks');
+
+  _.each(['assign', 'bindAll', 'defaults'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should not throw strict mode errors', function() {
+      var object = { 'a': null, 'b': function(){} },
+          pass = true;
+
+      if (freeze) {
+        freeze(object);
+        try {
+          if (methodName == 'bindAll') {
+            func(object);
+          } else {
+            func(object, { 'a': 1 });
+          }
+        } catch(e) {
+          pass = false;
+        }
+        ok(pass);
+      }
+      else {
+        skipTest();
+      }
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.filter');
+
+  (function() {
+    test('should not modify the resulting value from within `callback`', function() {
+      var actual = _.filter([0], function(value, index, array) {
+        return (array[index] = 1);
+      });
+
+      deepEqual(actual, [0]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.find');
+
+  (function() {
+    var objects = [
+      { 'a': 0, 'b': 0 },
+      { 'a': 1, 'b': 1 },
+      { 'a': 2, 'b': 2 }
+    ];
+
+    test('should return found `value`', function() {
+      equal(_.find(objects, function(object) { return object.a == 1; }), objects[1]);
+    });
+
+    test('should return `undefined` if `value` is not found', function() {
+      equal(_.find(objects, function(object) { return object.a == 3; }), undefined);
+    });
+
+    test('should work with an object for `callback`', function() {
+      equal(_.find(objects, { 'b': 2 }), objects[2]);
+    });
+
+    test('should work with a string for `callback`', function() {
+      equal(_.find(objects, 'b'), objects[1]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.first');
+
+  (function() {
+    var array = [1, 2, 3];
+
+    var objects = [
+      { 'a': 2, 'b': 2 },
+      { 'a': 1, 'b': 1 },
+      { 'a': 0, 'b': 0 }
+    ];
+
+    test('should return the first element', function() {
+      strictEqual(_.first(array), 1);
+    });
+
+    test('should return the first two elements', function() {
+      deepEqual(_.first(array, 2), [1, 2]);
+    });
+
+    test('should work with a `callback`', function() {
+      var actual = _.first(array, function(num) {
+        return num < 3;
+      });
+
+      deepEqual(actual, [1, 2]);
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args;
+
+      _.first(array, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [1, 0, array]);
+    });
+
+    test('supports the `thisArg` argument', function() {
+      var actual = _.first(array, function(value, index) {
+        return this[index] < 3;
+      }, array);
+
+      deepEqual(actual, [1, 2]);
+    });
+
+    test('should chain when passing `n`, `callback`, or `thisArg`', function() {
+      var actual = _(array).first(2);
+
+      ok(actual instanceof _);
+
+      actual = _(array).first(function(num) {
+        return num < 3;
+      });
+
+      ok(actual instanceof _);
+
+      actual = _(array).first(function(value, index) {
+        return this[index] < 3;
+      }, array);
+
+      ok(actual instanceof _);
+    });
+
+    test('should not chain when no arguments are passed', function() {
+      var actual = _(array).first();
+      strictEqual(actual, 1);
+    });
+
+    test('should work with an object for `callback`', function() {
+      deepEqual(_.first(objects, { 'b': 2 }), objects.slice(0, 1));
+    });
+
+    test('should work with a string for `callback`', function() {
+      deepEqual(_.first(objects, 'b'), objects.slice(0, 2));
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.flatten');
+
+  (function() {
+    test('should treat sparse arrays as dense', function() {
+      var array = [[1, 2, 3], Array(3)],
+          expected = [1, 2, 3],
+          actual1 = _.flatten(array),
+          actual2 = _.flatten(array, true);
+
+      expected.push(undefined, undefined, undefined);
+
+      deepEqual(actual1, expected);
+      ok(4 in actual1);
+
+      deepEqual(actual2, expected);
+      ok(4 in actual2);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.forEach');
+
+  (function() {
+    test('returns the collection', function() {
+      var collection = [1, 2, 3];
+      equal(_.forEach(collection, Boolean), collection);
+    });
+
+    _.each({
+      'literal': 'abc',
+      'object': Object('abc')
+    },
+    function(collection, key) {
+      test('should work with a string ' + key + ' for `collection` (test in IE < 9)', function() {
+        var args,
+            values = [];
+
+        _.forEach(collection, function(value) {
+          args || (args = slice.call(arguments));
+          values.push(value);
+        });
+
+        deepEqual(args, ['a', 0, collection]);
+        deepEqual(values, ['a', 'b', 'c']);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.forIn');
+
+  (function() {
+    test('iterates over inherited properties', function() {
+      function Dog(name) { this.name = name; }
+      Dog.prototype.bark = function() { /* Woof, woof! */ };
+
+      var keys = [];
+      _.forIn(new Dog('Dagny'), function(value, key) { keys.push(key); });
+      deepEqual(keys.sort(), ['bark', 'name']);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.forOwn');
+
+  (function() {
+    test('iterates over the `length` property', function() {
+      var keys = [],
+          object = { '0': 'zero', '1': 'one', 'length': 2 };
+
+      _.forOwn(object, function(value, key) { keys.push(key); });
+      deepEqual(keys.sort(), ['0', '1', 'length']);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('collection iteration bugs');
+
+  _.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
+      var keys = [];
+      func(shadowed, function(value, key) { keys.push(key); });
+      deepEqual(keys.sort(), shadowedKeys);
+    });
+
+    test('lodash.' + methodName + ' skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
+      function Foo() {}
+      Foo.prototype.a = 1;
+
+      var keys = [];
+      function callback(value, key) { keys.push(key); }
+
+      func(Foo, callback);
+      deepEqual(keys, []);
+      keys.length = 0;
+
+      Foo.prototype = { 'a': 1 };
+      func(Foo, callback);
+      deepEqual(keys, []);
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('object assignments');
+
+  _.each(['assign', 'defaults', 'merge'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should assign problem JScript properties (test in IE < 9)', function() {
+      var object = {
+        'constructor': 1,
+        'hasOwnProperty': 2,
+        'isPrototypeOf': 3,
+        'propertyIsEnumerable': undefined,
+        'toLocaleString': undefined,
+        'toString': undefined,
+        'valueOf': undefined
+      };
+
+      var source = {
+        'propertyIsEnumerable': 4,
+        'toLocaleString': 5,
+        'toString': 6,
+        'valueOf': 7
+      };
+
+      deepEqual(func(object, source), shadowed);
+    });
+
+    test('lodash.' + methodName + ' skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
+      function Foo() {}
+      Foo.prototype.c = 3;
+
+      Foo.a = 1;
+      Foo.b = 2;
+
+      var expected = { 'a': 1, 'b': 2 };
+      deepEqual(func({}, Foo), expected);
+
+      Foo.prototype = { 'c': 3 };
+      deepEqual(func({}, Foo), expected);
+    });
+
+    test('lodash.' + methodName + ' should work with `_.reduce`', function() {
+      var actual = { 'a': 1},
+          array = [{ 'b': 2 }, { 'c': 3 }];
+
+      _.reduce(array, func, actual);
+      deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3});
+    });
+  });
+
+  _.each(['assign', 'merge'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should pass the correct `callback` arguments', function() {
+      var args;
+
+      func({ 'a': 1 }, { 'a': 2 }, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [1, 2]);
+    });
+
+    test('lodash.' + methodName + ' should correct set the `this` binding', function() {
+      var actual = func({}, { 'a': 0 }, function(a, b) {
+        return this[b];
+      }, [2]);
+
+      deepEqual(actual, { 'a': 2 });
+    });
+
+    test('lodash.' + methodName + ' should not treat the second argument as a `callback`', function() {
+      function callback() {}
+      callback.b = 2;
+
+      var actual = func({ 'a': 1 }, callback);
+      deepEqual(actual, { 'a': 1, 'b': 2 });
+
+      actual = func({ 'a': 1 }, callback, { 'c': 3 });
+      deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 });
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('exit early');
+
+  _.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' can exit early when iterating arrays', function() {
+      var array = [1, 2, 3],
+          values = [];
+
+      func(array, function(value) { values.push(value); return false; });
+      deepEqual(values, [1]);
+    });
+
+    test('lodash.' + methodName + ' can exit early when iterating objects', function() {
+      var object = { 'a': 1, 'b': 2, 'c': 3 },
+          values = [];
+
+      func(object, function(value) { values.push(value); return false; });
+      equal(values.length, 1);
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.groupBy');
+
+  (function() {
+    test('supports the `thisArg` argument', function() {
+      var actual = _.groupBy([4.2, 6.1, 6.4], function(num) {
+        return this.floor(num);
+      }, Math);
+
+      deepEqual(actual, { '4': [4.2], '6': [6.1, 6.4] });
+    });
+
+    test('should only add values to own, not inherited, properties', function() {
+      var actual = _.groupBy([4.2, 6.1, 6.4], function(num) {
+        return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
+      });
+
+      deepEqual(actual.constructor, [4.2]);
+      deepEqual(actual.hasOwnProperty, [6.1, 6.4]);
+    });
+
+    test('should work with an object for `collection`', function() {
+      var actual = _.groupBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) {
+        return Math.floor(num);
+      });
+
+      deepEqual(actual, { '4': [4.2], '6': [6.1, 6.4] });
+    });
+
+    test('should work with a number for `callback`', function() {
+      var array = [
+        [1, 'a'],
+        [2, 'a'],
+        [2, 'b']
+      ];
+
+      deepEqual(_.groupBy(array, 0), { '1': [[1 , 'a']], '2': [[2, 'a'], [2, 'b']] });
+      deepEqual(_.groupBy(array, 1), { 'a': [[1 , 'a'], [2, 'a']], 'b': [[2, 'b']] });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.indexOf');
+
+  (function() {
+    var array = [1, 2, 3, 1, 2, 3];
+
+    test('should work with a positive `fromIndex`', function() {
+      equal(_.indexOf(array, 1, 2), 3);
+    });
+
+    test('should work with `fromIndex` >= `array.length`', function() {
+      equal(_.indexOf(array, 1, 6), -1);
+      equal(_.indexOf(array, undefined, 6), -1);
+      equal(_.indexOf(array, 1, 8), -1);
+      equal(_.indexOf(array, undefined, 8), -1);
+    });
+
+    test('should work with a negative `fromIndex`', function() {
+      equal(_.indexOf(array, 2, -3), 4);
+    });
+
+    test('should work with a negative `fromIndex` <= `-array.length`', function() {
+      strictEqual(_.indexOf(array, 1, -6), 0);
+      strictEqual(_.indexOf(array, 2, -8), 1);
+    });
+
+    test('should ignore non-number `fromIndex` values', function() {
+      strictEqual(_.indexOf([1, 2, 3], 1, '1'), 0);
+    });
+
+    test('should work with `isSorted`', function() {
+      strictEqual(_.indexOf([1, 2, 3], 1, true), 0);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.initial');
+
+  (function() {
+    var array = [1, 2, 3];
+
+    var objects = [
+      { 'a': 0, 'b': 0 },
+      { 'a': 1, 'b': 1 },
+      { 'a': 2, 'b': 2 }
+    ];
+
+    test('returns all elements for `n` of `0`', function() {
+      deepEqual(_.initial(array, 0), [1, 2, 3]);
+    });
+
+    test('should allow a falsey `array` argument', function() {
+      _.each(falsey, function(index, value) {
+        try {
+          var actual = index ? _.initial(value) : _.initial();
+        } catch(e) { }
+        deepEqual(actual, []);
+      })
+    });
+
+    test('should exclude last element', function() {
+      deepEqual(_.initial(array), [1, 2]);
+    });
+
+    test('should exlcude the last two elements', function() {
+      deepEqual(_.initial(array, 2), [1]);
+    });
+
+    test('should work with a `callback`', function() {
+      var actual = _.initial(array, function(num) {
+        return num > 1;
+      });
+
+      deepEqual(actual, [1]);
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args;
+
+      _.initial(array, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [3, 2, array]);
+    });
+
+    test('supports the `thisArg` argument', function() {
+      var actual = _.initial(array, function(value, index) {
+        return this[index] > 1;
+      }, array);
+
+      deepEqual(actual, [1]);
+    });
+
+    test('should work with an object for `callback`', function() {
+      deepEqual(_.initial(objects, { 'b': 2 }), objects.slice(0, 2));
+    });
+
+    test('should work with a string for `callback`', function() {
+      deepEqual(_.initial(objects, 'b'), objects.slice(0, 1));
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.invoke');
+
+  (function() {
+    test('should work with an object for `collection`', function() {
+      var object = { 'a': 1, 'b': 2, 'c': 3 };
+      deepEqual(_.invoke(object, 'toFixed', 1), ['1.0', '2.0', '3.0']);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isElement');
+
+  (function() {
+    test('should use strict equality in its duck type check', function() {
+      var element = window.document ? document.body : { 'nodeType': 1 };
+      strictEqual(_.isElement(element), true);
+
+      strictEqual(_.isElement({ 'nodeType': new Number(1) }), false);
+      strictEqual(_.isElement({ 'nodeType': true }), false);
+      strictEqual(_.isElement({ 'nodeType': [1] }), false);
+      strictEqual(_.isElement({ 'nodeType': '1' }), false);
+      strictEqual(_.isElement({ 'nodeType': '001' }), false);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isEmpty');
+
+  (function() {
+    var args = arguments;
+
+    test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
+      equal(_.isEmpty(shadowed), false);
+    });
+
+    test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
+      function Foo() {}
+      Foo.prototype.a = 1;
+      strictEqual(_.isEmpty(Foo), true);
+
+      Foo.prototype = { 'a': 1 };
+      strictEqual(_.isEmpty(Foo), true);
+    });
+
+    test('should work with an object that has a `length` property', function() {
+      strictEqual(_.isEmpty({ 'length': 0 }), false);
+    });
+
+    test('should work with jQuery/MooTools DOM query collections', function() {
+      function Foo(elements) { Array.prototype.push.apply(this, elements); }
+      Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice };
+
+      strictEqual(_.isEmpty(new Foo([])), true);
+    });
+
+    test('should work with `arguments` objects (test in IE < 9)', function() {
+      strictEqual(_.isEmpty(args), false);
+    });
+  }(1, 2, 3));
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isEqual');
+
+  (function() {
+    test('should work with `arguments` objects (test in IE < 9)', function() {
+      var args1 = (function() { return arguments; }(1, 2, 3)),
+          args2 = (function() { return arguments; }(1, 2, 3)),
+          args3 = (function() { return arguments; }(1, 2));
+
+      strictEqual(_.isEqual(args1, args2), true);
+      strictEqual(_.isEqual(args1, args3), false);
+    });
+
+    test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
+      strictEqual(_.isEqual(shadowed, {}), false);
+    });
+
+    test('should return `true` for like-objects from different documents', function() {
+      // ensure `_._object` is assigned (unassigned in Opera 10.00)
+      if (_._object) {
+        var object = { 'a': 1, 'b': 2, 'c': 3 };
+        strictEqual(_.isEqual(object, _._object), true);
+      } else {
+        skipTest();
+      }
+    });
+
+    test('should return `false` when comparing values with circular references to unlike values', function() {
+      var array1 = ['a', null, 'c'],
+          array2 = ['a', [], 'c'],
+          object1 = { 'a': 1, 'b': null, 'c': 3 },
+          object2 = { 'a': 1, 'b': {}, 'c': 3 };
+
+      array1[1] = array1;
+      strictEqual(_.isEqual(array1, array2), false);
+
+      object1.b = object1;
+      strictEqual(_.isEqual(object1, object2), false);
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args;
+
+      _.isEqual('a', 'b', function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, ['a', 'b']);
+    });
+
+    test('should correct set the `this` binding', function() {
+      var actual = _.isEqual('a', 'b', function(a, b) {
+        return this[a] == this[b];
+      }, { 'a': 1, 'b': 1 });
+
+      strictEqual(actual, true);
+    });
+
+    test('should handle comparisons if `callback` returns `undefined`', function() {
+      var actual = _.isEqual('a', 'a', function() { });
+      strictEqual(actual, true);
+    });
+
+    test('should return a boolean value even if `callback` does not', function() {
+      var actual = _.isEqual('a', 'a', function() { return 'a'; });
+      strictEqual(actual, true);
+
+      _.each(falsey, function(value) {
+        var actual = _.isEqual('a', 'b', function() { return value; });
+        strictEqual(actual, false);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isFinite');
+
+  (function() {
+    test('should return `false` for non-numeric values', function() {
+      strictEqual(_.isFinite(null), false);
+      strictEqual(_.isFinite([]), false);
+      strictEqual(_.isFinite(true), false);
+      strictEqual(_.isFinite(''), false);
+      strictEqual(_.isFinite(' '), false);
+      strictEqual(_.isFinite('2px'), false);
+    });
+
+    test('should return `true` for numeric string values', function() {
+      strictEqual(_.isFinite('2'), true);
+      strictEqual(_.isFinite('0'), true);
+      strictEqual(_.isFinite('08'), true);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isObject');
+
+  (function() {
+    test('should avoid V8 bug #2291', function() {
+      // trigger V8 bug
+      // http://code.google.com/p/v8/issues/detail?id=2291
+      var obj = {},
+          str = 'foo';
+
+      // 1: Useless comparison statement, this is half the trigger
+      obj == obj;
+      // 2: Initial check with object, this is the other half of the trigger
+      _.isObject(obj);
+
+      equal(_.isObject(str), false);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isNaN');
+
+  (function() {
+    test('returns `true` for `new Number(NaN)`', function() {
+      strictEqual(_.isNaN(new Number(NaN)), true);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isNumber');
+
+  (function() {
+    test('should avoid `[xpconnect wrapped native prototype]` in Firefox', function() {
+      strictEqual(_.isNumber(+"2"), true);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.isPlainObject');
+
+  (function() {
+    test('should detect plain objects', function() {
+      function Foo(a) {
+        this.a = 1;
+      }
+
+      strictEqual(_.isPlainObject(new Foo(1)), false);
+      strictEqual(_.isPlainObject([1, 2, 3]), false);
+      strictEqual(_.isPlainObject({ 'a': 1 }), true);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('isType checks');
+
+  _.each([
+    'isArguments',
+    'isArray',
+    'isBoolean',
+    'isDate',
+    'isElement',
+    'isEmpty',
+    'isEqual',
+    'isFinite',
+    'isFunction',
+    'isNaN',
+    'isNull',
+    'isNumber',
+    'isObject',
+    'isRegExp',
+    'isString',
+    'isUndefined'
+  ],
+  function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should return a boolean', function() {
+      var expected = 'boolean';
+
+      equal(typeof func(arguments), expected);
+      equal(typeof func([]), expected);
+      equal(typeof func(true), expected);
+      equal(typeof func(false), expected);
+      equal(typeof func(new Date), expected);
+      equal(typeof func(window.document && document.body), expected);
+      equal(typeof func({}), expected);
+      equal(typeof func(undefined), expected);
+      equal(typeof func(Infinity), expected);
+      equal(typeof func(_), expected);
+      equal(typeof func(NaN), expected);
+      equal(typeof func(null), expected);
+      equal(typeof func(0), expected);
+      equal(typeof func({ 'a': 1 }), expected);
+      equal(typeof func('a'), expected);
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.keys');
+
+  (function() {
+    var args = arguments;
+
+    test('should work with `arguments` objects (test in IE < 9)', function() {
+      deepEqual(_.keys(args), ['0', '1', '2']);
+    });
+
+    test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
+      function Foo() {}
+      Foo.prototype.a = 1;
+
+      deepEqual(_.keys(Foo.prototype), ['a']);
+      deepEqual(_.keys(shadowed).sort(), shadowedKeys);
+    });
+
+    test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
+      function Foo() {}
+      Foo.prototype.c = 3;
+
+      Foo.a = 1;
+      Foo.b = 2;
+
+      var expected = ['a', 'b'];
+      deepEqual(_.keys(Foo), expected);
+
+      Foo.prototype = { 'c': 3 };
+      deepEqual(_.keys(Foo), expected);
+    });
+  }(1, 2, 3));
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.last');
+
+  (function() {
+    var array = [1, 2, 3];
+
+    var objects = [
+      { 'a': 0, 'b': 0 },
+      { 'a': 1, 'b': 1 },
+      { 'a': 2, 'b': 2 }
+    ];
+
+    test('should return the last element', function() {
+      equal(_.last(array), 3);
+    });
+
+    test('should return the last two elements', function() {
+      deepEqual(_.last(array, 2), [2, 3]);
+    });
+
+    test('should work with a `callback`', function() {
+      var actual = _.last(array, function(num) {
+        return num > 1;
+      });
+
+      deepEqual(actual, [2, 3]);
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args;
+
+      _.last(array, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [3, 2, array]);
+    });
+
+    test('supports the `thisArg` argument', function() {
+      var actual = _.last(array, function(value, index) {
+        return this[index] > 1;
+      }, array);
+
+      deepEqual(actual, [2, 3]);
+    });
+
+    test('should chain when passing `n`, `callback`, or `thisArg`', function() {
+      var actual = _(array).last(2);
+
+      ok(actual instanceof _);
+
+      actual = _(array).last(function(num) {
+        return num > 1;
+      });
+
+      ok(actual instanceof _);
+
+      actual = _(array).last(function(value, index) {
+        return this[index] > 1;
+      }, array);
+
+      ok(actual instanceof _);
+    });
+
+    test('should not chain when no arguments are passed', function() {
+      var actual = _(array).last();
+      equal(actual, 3);
+    });
+
+    test('should work with an object for `callback`', function() {
+      deepEqual(_.last(objects, { 'b': 2 }), objects.slice(-1));
+    });
+
+    test('should work with a string for `callback`', function() {
+      deepEqual(_.last(objects, 'b'), objects.slice(-2));
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.lastIndexOf');
+
+  (function() {
+    var array = [1, 2, 3, 1, 2, 3];
+
+    test('should work with a positive `fromIndex`', function() {
+      strictEqual(_.lastIndexOf(array, 1, 2), 0);
+    });
+
+    test('should work with `fromIndex` >= `array.length`', function() {
+      equal(_.lastIndexOf(array, undefined, 6), -1);
+      equal(_.lastIndexOf(array, 1, 6), 3);
+      equal(_.lastIndexOf(array, undefined, 8), -1);
+      equal(_.lastIndexOf(array, 1, 8), 3);
+    });
+
+    test('should work with a negative `fromIndex`', function() {
+      strictEqual(_.lastIndexOf(array, 2, -3), 1);
+    });
+
+    test('should work with a negative `fromIndex` <= `-array.length`', function() {
+      strictEqual(_.lastIndexOf(array, 1, -6), 0);
+      equal(_.lastIndexOf(array, 2, -8), -1);
+    });
+
+    test('should ignore non-number `fromIndex` values', function() {
+      equal(_.lastIndexOf([1, 2, 3], 3, '1'), 2);
+      equal(_.lastIndexOf([1, 2, 3], 3, true), 2);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.map');
+
+  (function() {
+    test('should return the correct result when iterating an object', function() {
+      var actual = _.map({ 'a': 1, 'b': 2, 'c': 3 }, function(value) {
+        return value;
+      });
+      deepEqual(actual, [1, 2, 3]);
+    });
+
+    test('should handle object arguments with non-numeric length properties', function() {
+      if (setDescriptor) {
+        var object = {};
+        setDescriptor(object, 'length', { 'value': 'x' });
+        deepEqual(_.map(object, _.identity), []);
+      } else {
+        skipTest();
+      }
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.max and lodash.min object iteration');
+
+  _.each(['max', 'min'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should iterate an object', function() {
+      var actual = func({ 'a': 1, 'b': 2, 'c': 3 });
+      equal(actual, methodName == 'max' ? 3 : 1);
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.max and lodash.min string iteration');
+
+  _.each(['max', 'min'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' should iterate a string', function() {
+      _.each(['abc', Object('abc')], function(value) {
+        var actual = func(value);
+        equal(actual, methodName == 'max' ? 'c' : 'a');
+      });
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.merge');
+
+  (function() {
+    var args = arguments;
+
+    test('should merge `source` into the destination object', function() {
+      var names = {
+        'stooges': [
+          { 'name': 'moe' },
+          { 'name': 'larry' }
+        ]
+      };
+
+      var ages = {
+        'stooges': [
+          { 'age': 40 },
+          { 'age': 50 }
+        ]
+      };
+
+      var heights = {
+        'stooges': [
+          { 'height': '5\'4"' },
+          { 'height': '5\'5"' }
+        ]
+      };
+
+      var expected = {
+        'stooges': [
+          { 'name': 'moe', 'age': 40, 'height': '5\'4"' },
+          { 'name': 'larry', 'age': 50, 'height': '5\'5"' }
+        ]
+      };
+
+      deepEqual(_.merge(names, ages, heights), expected);
+    });
+
+    test('should merge sources containing circular references', function() {
+      var object = {
+        'foo': { 'a': 1 },
+        'bar': { 'a': 2 }
+      };
+
+      var source = {
+        'foo': { 'b': { 'foo': { 'c': { } } } },
+        'bar': { }
+      };
+
+      source.foo.b.foo.c = source;
+      source.bar.b = source.foo.b;
+
+      var actual = _.merge(object, source);
+      ok(actual.bar.b === actual.foo.b && actual.foo.b.foo.c === actual.foo.b.foo.c.foo.b.foo.c);
+    });
+
+    test('should not treat `arguments` objects as plain objects', function() {
+      var object = {
+        'args': args
+      };
+
+      var source = {
+        'args': { '3': 4 }
+      };
+
+      var actual = _.merge(object, source);
+      equal(_.isArguments(actual.args), false);
+    });
+
+    test('should work with four arguments', function() {
+      var expected = { 'a': 4 };
+      deepEqual(_.merge({ 'a': 1 }, { 'a': 2 }, { 'a': 3 }, expected), expected);
+    });
+
+    test('should assign `null` values', function() {
+      var actual = _.merge({ 'a': 1 }, { 'a': null });
+      strictEqual(actual.a, null);
+    });
+
+    test('should not assign `undefined` values', function() {
+      var actual = _.merge({ 'a': 1 }, { 'a': undefined });
+      strictEqual(actual.a, 1);
+    });
+
+    test('should handle merging if `callback` returns `undefined`', function() {
+      var actual = _.merge({ 'a': 1 }, { 'a': 2 }, function() { });
+      deepEqual(actual, { 'a': 2 });
+    });
+  }(1, 2, 3));
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.omit');
+
+  (function() {
+    var object = { 'a': 1, 'b': 2 },
+        expected = { 'b': 2 };
+
+    test('should accept individual property names', function() {
+      deepEqual(_.omit(object, 'a'), expected);
+    });
+
+    test('should accept an array of property names', function() {
+      deepEqual(_.omit(object, ['a', 'c']), expected);
+    });
+
+    test('should accept mixes of individual and arrays of property names', function() {
+      deepEqual(_.omit(object, ['a'], 'c'), expected);
+    });
+
+    test('should iterate over inherited properties', function() {
+      function Foo() {}
+      Foo.prototype = object;
+
+      deepEqual(_.omit(new Foo, 'a'), expected);
+    });
+
+    test('should work with a `callback` argument', function() {
+      var actual = _.omit(object, function(value) {
+        return value == 1;
+      });
+
+      deepEqual(actual, expected);
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args,
+          lastKey = _.keys(object).pop();
+
+      var expected = lastKey == 'b'
+        ? [1, 'a', object]
+        : [2, 'b', object];
+
+      _.omit(object, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, expected);
+    });
+
+    test('should correct set the `this` binding', function() {
+      var actual = _.omit(object, function(value) {
+        return value == this.a;
+      }, { 'a': 1 });
+
+      deepEqual(actual, expected);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('partial methods');
+
+  _.each(['partial', 'partialRight'], function(methodName) {
+    var func = _[methodName];
+
+    test('lodash.' + methodName + ' partially applies an argument, without additional arguments', function() {
+      var arg = 'a',
+          fn = function(x) { return x; };
+
+      equal(func(fn, arg)(), arg);
+    });
+
+    test('lodash.' + methodName + ' partially applies an argument, with additional arguments', function() {
+      var arg1 = 'a',
+          arg2 = 'b',
+          expected = [arg1, arg2],
+          fn = function(x, y) { return [x, y]; };
+
+      if (methodName == 'partialRight') {
+        expected.reverse();
+      }
+      deepEqual(func(fn, arg1)(arg2), expected);
+    });
+
+    test('lodash.' + methodName + ' works without partially applying arguments, without additional arguments', function() {
+      var fn = function() { return arguments.length; };
+      strictEqual(func(fn)(), 0);
+    });
+
+    test('lodash.' + methodName + ' works without partially applying arguments, with additional arguments', function() {
+      var arg = 'a',
+          fn = function(x) { return x; };
+
+      equal(func(fn)(arg), arg);
+    });
+
+    test('lodash.' + methodName + ' should not alter the `this` binding of either function', function() {
+      var object = { 'a': 1 },
+          fn = function() { return this.a; };
+
+      strictEqual(func(_.bind(fn, object))(), object.a);
+      strictEqual(_.bind(func(fn), object)(), object.a);
+    });
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.partialRight');
+
+  (function() {
+    test('should work as a deep `_.defaults`', function() {
+      var object = { 'a': { 'b': 1 } },
+          source = { 'a': { 'b': 2, 'c': 3 } },
+          expected = { 'a': { 'b': 1, 'c': 3 } };
+
+      var deepDefaults = _.partialRight(_.merge, _.defaults);
+      deepEqual(deepDefaults(object, source), expected);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.pick');
+
+  (function() {
+    var object = { 'a': 1, 'b': 2 };
+
+    test('should iterate over inherited properties', function() {
+      function Foo() {}
+      Foo.prototype = object;
+
+      deepEqual(_.pick(new Foo, 'b'), { 'b': 2 });
+    });
+
+    test('should work with a `callback` argument', function() {
+      var actual = _.pick(object, function(value) {
+        return value == 2;
+      });
+
+      deepEqual(actual, { 'b': 2 });
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args,
+          lastKey = _.keys(object).pop();
+
+      var expected = lastKey == 'b'
+        ? [1, 'a', object]
+        : [2, 'b', object];
+
+      _.pick(object, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, expected);
+    });
+
+    test('should correct set the `this` binding', function() {
+      var actual = _.pick(object, function(value) {
+        return value == this.b;
+      }, { 'b': 2 });
+
+      deepEqual(actual, { 'b': 2 });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.pluck');
+
+  (function() {
+    test('should work with an object for `collection`', function() {
+      var object = { 'a': [1], 'b': [1, 2], 'c': [1, 2, 3] };
+      deepEqual(_.pluck(object, 'length'), [1, 2, 3]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.random');
+
+  (function() {
+    test('should return `0` or `1` when no arguments are passed', function() {
+      var actual = _.random();
+      ok(actual === 0 || actual === 1);
+    });
+
+    test('supports not passing a `max` argument', function() {
+      var actual = _.random(5),
+          start = new Date;
+
+      while ((new Date - start) < 50 && actual == 5) {
+        actual = _.random(5);
+      }
+      notEqual(actual, 5);
+    });
+
+    test('supports large integer values', function() {
+      var array = Array(1000),
+          min = Math.pow(2, 31),
+          max = Math.pow(2, 62);
+
+      strictEqual(_.every(array, function() {
+        return _.random(min, max) >= min;
+      }), true);
+
+      strictEqual(_.some(array, function() {
+        return _.random(Number.MAX_VALUE) > 0;
+      }), true);
+    });
+
+    test('should coerce arguments to numbers', function() {
+      strictEqual(_.random('1', '1'), 1);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.range');
+
+  (function() {
+    var func = _.range;
+
+    test('should treat falsey `start` arguments as `0`', function() {
+      _.each(falsey, function(value, index) {
+        if (index) {
+          deepEqual(_.range(value), []);
+          deepEqual(_.range(value, 1), [0]);
+        } else {
+          deepEqual(_.range(), []);
+        }
+      });
+    });
+
+    test('should coerce arguments to numbers', function() {
+      var actual = [func('0',1), func('1'), func(0, 1, '1')];
+      deepEqual(actual, [[0], [0], [0]]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.reduce');
+
+  (function() {
+    test('should pass the correct `callback` arguments', function() {
+      var args,
+          array = [1, 2, 3];
+
+      _.reduce(array, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [1, 2, 1, array]);
+    });
+
+    _.each({
+      'literal': 'abc',
+      'object': Object('abc')
+    },
+    function(collection, key) {
+      test('should work with a string ' + key + ' for `collection` (test in IE < 9)', function() {
+        var args;
+
+        var actual = _.reduce(collection, function(accumulator, value) {
+          args || (args = slice.call(arguments));
+          return accumulator + value;
+        });
+
+        deepEqual(args, ['a', 'b', 1, collection]);
+        equal(actual, 'abc');
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.reduceRight');
+
+  (function() {
+    test('should pass the correct `callback` arguments when iterating an array', function() {
+      var args,
+          array = [1, 2, 3];
+
+      _.reduceRight(array, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [3, 2, 1, array]);
+    });
+
+    test('should pass the correct `callback` arguments when iterating an object', function() {
+      var args,
+          object = { 'a': 1, 'b': 2 },
+          lastKey = _.keys(object).pop();
+
+      var expected = lastKey == 'b'
+        ? [2, 1, 'a', object]
+        : [1, 2, 'b', object];
+
+      _.reduceRight(object, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, expected);
+    });
+
+    _.each({
+      'literal': 'abc',
+      'object': Object('abc')
+    },
+    function(collection, key) {
+      test('should work with a string ' + key + ' for `collection` (test in IE < 9)', function() {
+        var args;
+
+        var actual = _.reduceRight(collection, function(accumulator, value) {
+          args || (args = slice.call(arguments));
+          return accumulator + value;
+        });
+
+        deepEqual(args, ['c', 'b', 1, collection]);
+        equal(actual, 'cba');
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.result');
+
+  (function() {
+    test('should return `undefined` when passed a falsey `object` argument', function() {
+      strictEqual(_.result(), undefined);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.rest');
+
+  (function() {
+    var array = [1, 2, 3];
+
+    var objects = [
+      { 'a': 2, 'b': 2 },
+      { 'a': 1, 'b': 1 },
+      { 'a': 0, 'b': 0 }
+    ];
+
+    test('returns all elements for `n` of `0`', function() {
+      deepEqual(_.rest(array, 0), [1, 2, 3]);
+    });
+
+    test('should allow a falsey `array` argument', function() {
+      _.each(falsey, function(index, value) {
+        try {
+          var actual = index ? _.rest(value) : _.rest();
+        } catch(e) { }
+        deepEqual(actual, []);
+      })
+    });
+
+    test('should exclude the first element', function() {
+      deepEqual(_.rest(array), [2, 3]);
+    });
+
+    test('should exclude the first two elements', function() {
+      deepEqual(_.rest(array, 2), [3]);
+    });
+
+    test('should work with a `callback`', function() {
+      var actual = _.rest(array, function(num) {
+        return num < 3;
+      });
+
+      deepEqual(actual, [3]);
+    });
+
+    test('should pass the correct `callback` arguments', function() {
+      var args;
+
+      _.rest(array, function() {
+        args || (args = slice.call(arguments));
+      });
+
+      deepEqual(args, [1, 0, array]);
+    });
+
+    test('supports the `thisArg` argument', function() {
+      var actual = _.rest(array, function(value, index) {
+        return this[index] < 3;
+      }, array);
+
+      deepEqual(actual, [3]);
+    });
+
+    test('should work with an object for `callback`', function() {
+      deepEqual(_.rest(objects, { 'b': 2 }), objects.slice(-2));
+    });
+
+    test('should work with a string for `callback`', function() {
+      deepEqual(_.rest(objects, 'b'), objects.slice(-1));
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.shuffle');
+
+  (function() {
+    test('should shuffle an object', function() {
+      var actual = _.shuffle({ 'a': 1, 'b': 2, 'c': 3 });
+      deepEqual(actual.sort(), [1, 2, 3]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.size');
+
+  (function() {
+    var args = arguments;
+
+    test('should allow a falsey `object` argument', function() {
+      _.each(falsey, function(index, value) {
+        try {
+          var actual = index ? _.size(value) : _.size();
+        } catch(e) { }
+        strictEqual(actual, 0);
+      })
+    });
+
+    test('should work with jQuery/MooTools DOM query collections', function() {
+      function Foo(elements) { Array.prototype.push.apply(this, elements); }
+      Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice };
+
+      equal(_.size(new Foo([1, 2, 3])), 3);
+    });
+
+    test('should work with `arguments` objects (test in IE < 9)', function() {
+      equal(_.size(args), 3);
+    });
+
+    test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
+      equal(_.size(shadowed), 7);
+    });
+
+    _.each({
+      'literal': 'abc',
+      'object': Object('abc')
+    },
+    function(collection, key) {
+      test('should work with a string ' + key + ' for `collection`', function() {
+        deepEqual(_.size(collection), 3);
+      });
+    });
+  }(1, 2, 3));
+
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.some');
+
+  (function() {
+    test('should return `true` as soon as the `callback` result is truthy', function() {
+      strictEqual(_.some([null, true, null], _.identity), true);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.sortBy');
+
+  (function() {
+    test('should perform a stable sort (test in IE > 8, Opera, and V8)', function() {
+      function Pair(x, y) {
+        this.x = x;
+        this.y = y;
+      }
+
+      var collection = [
+        new Pair(1, 1), new Pair(1, 2),
+        new Pair(1, 3), new Pair(1, 4),
+        new Pair(1, 5), new Pair(1, 6),
+        new Pair(2, 1), new Pair(2, 2),
+        new Pair(2, 3), new Pair(2, 4),
+        new Pair(2, 5), new Pair(2, 6),
+        new Pair(undefined, 1), new Pair(undefined, 2),
+        new Pair(undefined, 3), new Pair(undefined, 4),
+        new Pair(undefined, 5), new Pair(undefined, 6)
+      ];
+
+      var actual = _.sortBy(collection, function(pair) {
+        return pair.x;
+      });
+
+      deepEqual(actual, collection);
+    });
+
+    test('supports the `thisArg` argument', function() {
+      var actual = _.sortBy([1, 2, 3], function(num) {
+        return this.sin(num);
+      }, Math);
+
+      deepEqual(actual, [3, 1, 2]);
+    });
+
+    test('should work with an object for `collection`', function() {
+      var actual = _.sortBy({ 'a': 1, 'b': 2, 'c': 3 }, function(num) {
+        return Math.sin(num);
+      });
+
+      deepEqual(actual, [3, 1, 2]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.sortedIndex');
+
+  (function() {
+    test('supports the `thisArg` argument', function() {
+      var actual = _.sortedIndex([1, 2, 3], 4, function(num) {
+        return this.sin(num);
+      }, Math);
+
+      strictEqual(actual, 0);
+    });
+
+    test('supports arrays with lengths larger than `Math.pow(2, 31) - 1`', function() {
+      var length = Math.pow(2, 32) - 1,
+          index = length - 1,
+          array = Array(length),
+          steps = 0;
+
+      array[index] = index;
+      _.sortedIndex(array, index, function() { steps++; });
+      equal(steps, 33);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.template');
+
+  (function() {
+    test('supports recursive calls', function() {
+      var compiled = _.template('<%= a %><% a = _.template(c, obj) %><%= a %>'),
+          data = { 'a': 'A', 'b': 'B', 'c': '<%= b %>' };
+
+      equal(compiled(data), 'AB');
+    });
+
+    test('should not augment the `options` object', function() {
+      var options = {};
+      _.template('', null, options);
+      deepEqual(options, {});
+    });
+
+    test('should provide the template source when a SyntaxError occurs', function() {
+      try {
+        _.template('<% if x %>');
+      } catch(e) {
+        var source = e.source;
+      }
+      ok(/__p/.test(source));
+    });
+
+    test('should work with complex "interpolate" delimiters', function() {
+      _.each({
+        '<%= a + b %>': '3',
+        '<%= b - a %>': '1',
+        '<%= a = b %>': '2',
+        '<%= !a %>': 'false',
+        '<%= ~a %>': '-2',
+        '<%= a * b %>': '2',
+        '<%= a / b %>': '0.5',
+        '<%= a % b %>': '1',
+        '<%= a >> b %>': '0',
+        '<%= a << b %>': '4',
+        '<%= a & b %>': '0',
+        '<%= a ^ b %>': '3',
+        '<%= a | b %>': '3',
+        '<%= {}.toString.call(0) %>': '[object Number]',
+        '<%= a.toFixed(2) %>': '1.00',
+        '<%= obj["a"] %>': '1',
+        '<%= delete a %>': 'true',
+        '<%= "a" in obj %>': 'true',
+        '<%= obj instanceof Object %>': 'true',
+        '<%= new Boolean %>': 'false',
+        '<%= typeof a %>': 'number',
+        '<%= void a %>': ''
+      },
+      function(value, key) {
+        var compiled = _.template(key),
+            data = { 'a': 1, 'b': 2 };
+
+        equal(compiled(data), value, key);
+      });
+    });
+
+    test('should allow referencing variables declared in "evaluate" delimiters from other delimiters', function() {
+      var compiled = _.template('<% var b = a; %><%= b.value %>'),
+          data = { 'a': { 'value': 1 } };
+
+      equal(compiled(data), '1');
+    });
+
+    test('should work when passing `options.variable`', function() {
+      var compiled = _.template(
+        '<% _.forEach( data.a, function( value ) { %>' +
+            '<%= value.valueOf() %>' +
+        '<% }) %>', null, { 'variable': 'data' }
+      );
+
+      var data = { 'a': [1, 2, 3] };
+
+      try {
+        equal(compiled(data), '123');
+      } catch(e) {
+        ok(false);
+      }
+    });
+
+    test('should not error with IE conditional comments enabled (test with development build)', function() {
+      var compiled = _.template(''),
+          pass = true;
+
+      /*@cc_on @*/
+      try {
+        compiled();
+      } catch(e) {
+        pass = false;
+      }
+      ok(pass);
+    });
+
+    test('should tokenize delimiters', function() {
+      var compiled = _.template('<span class="icon-<%= type %>2"></span>'),
+          data = { 'type': 1 };
+
+      equal(compiled(data), '<span class="icon-12"></span>');
+    });
+
+    test('should work with "interpolate" delimiters containing ternary operators', function() {
+      var compiled = _.template('<%= value ? value : "b" %>'),
+          data = { 'value': 'a' };
+
+      equal(compiled(data), 'a');
+    });
+
+    test('should work with "interpolate" delimiters containing global values', function() {
+      var compiled = _.template('<%= typeof QUnit.init %>');
+
+      try {
+        var actual = compiled();
+      } catch(e) { }
+
+      equal(actual, 'function');
+    });
+
+    test('should parse delimiters with newlines', function() {
+      var expected = '<<\nprint("<p>" + (value ? "yes" : "no") + "</p>")\n>>',
+          compiled = _.template(expected, null, { 'evaluate': /<<(.+?)>>/g }),
+          data = { 'value': true };
+
+      equal(compiled(data), expected);
+    });
+
+    test('should parse ES6 template delimiters', function() {
+      var data = { 'value': 2 };
+      equal(_.template('1${value}3', data), '123');
+      equal(_.template('${"{" + value + "\\}"}', data), '{2}');
+    });
+
+    test('supports the "imports" option', function() {
+      var options = { 'imports': { 'a': 1 } },
+          compiled = _.template('<%= a %>', null, options);
+
+      equal(compiled({}), '1');
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.throttle');
+
+  (function() {
+    test('subsequent calls should return the result of the first call', function() {
+      var throttled = _.throttle(function(value) { return value; }, 32),
+          result = [throttled('x'), throttled('y')];
+
+      deepEqual(result, ['x', 'x']);
+    });
+
+    test('should clear timeout when `func` is called', function() {
+      var counter = 0,
+          oldDate = Date,
+          throttled = _.throttle(function() { counter++; }, 32);
+
+      throttled();
+      throttled();
+
+      window.Date = function() { return Object(Infinity); };
+      throttled();
+      window.Date = oldDate;
+
+      equal(counter, 2);
+    });
+
+    asyncTest('supports recursive calls', function() {
+      var counter = 0;
+      var throttled = _.throttle(function() {
+        counter++;
+        if (counter < 10) {
+          throttled();
+        }
+      }, 32);
+
+      throttled();
+      equal(counter, 1);
+
+      setTimeout(function() {
+        ok(counter < 3)
+        QUnit.start();
+      }, 32);
+    });
+
+    asyncTest('should not trigger a trailing call when invoked once', function() {
+      var counter = 0,
+          throttled = _.throttle(function() { counter++; }, 32);
+
+      throttled();
+      equal(counter, 1);
+
+      setTimeout(function() {
+        equal(counter, 1);
+        QUnit.start();
+      }, 96);
+    });
+
+    asyncTest('should trigger trailing call when invoked repeatedly', function() {
+      var counter = 0,
+          limit = 48,
+          throttled = _.throttle(function() { counter++; }, 32),
+          start = new Date;
+
+      while ((new Date - start) < limit) {
+        throttled();
+      }
+      var lastCount = counter;
+      ok(lastCount > 1);
+
+      setTimeout(function() {
+        ok(counter > lastCount);
+        QUnit.start();
+      }, 96);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.toArray');
+
+  (function() {
+    var args = arguments;
+
+    test('should return a dense array', function() {
+      var array = Array(3);
+      array[1] = 2;
+
+      var actual = _.toArray(array);
+
+      ok(0 in actual);
+      ok(2 in actual);
+      deepEqual(actual, array);
+    });
+
+    test('should treat array-like objects like arrays', function() {
+      var object = { '0': 'a', '1': 'b', '2': 'c', 'length': 3 };
+      deepEqual(_.toArray(object), ['a', 'b', 'c']);
+      deepEqual(_.toArray(args), [1, 2, 3]);
+    });
+
+    test('should work with a string for `collection` (test in Opera < 10.52)', function() {
+      deepEqual(_.toArray('abc'), ['a', 'b', 'c']);
+      deepEqual(_.toArray(Object('abc')), ['a', 'b', 'c']);
+    });
+
+    test('should work with a node list for `collection` (test in IE < 9)', function() {
+      if (window.document) {
+        try {
+          var nodeList = document.getElementsByTagName('body'),
+              body = nodeList[0],
+              actual = _.toArray(nodeList);
+        } catch(e) { }
+        deepEqual(actual, [body]);
+      } else {
+        skipTest();
+      }
+    });
+  }(1, 2, 3));
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.times');
+
+  (function() {
+    test('should return an array of the results of each `callback` execution', function() {
+      deepEqual(_.times(3, function(n) { return n * 2; }), [0, 2, 4]);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.unescape');
+
+  (function() {
+    var escaped = '&amp;&lt;&gt;&quot;&#39;\/',
+        unescaped = '&<>"\'\/';
+
+    test('should unescape entities in the correct order', function() {
+      equal(_.unescape('&amp;lt;'), '&lt;');
+    });
+
+    test('should unescape the proper entities', function() {
+      equal(_.unescape(escaped), unescaped);
+    });
+
+    test('should unescape the same characters escaped by `_.escape`', function() {
+      equal(_.unescape(_.escape(unescaped)), unescaped);
+    });
+
+    test('should return an empty string when passed `null` or `undefined`', function() {
+      equal(_.unescape(null), '');
+      equal(_.unescape(undefined), '');
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.uniq');
+
+  (function() {
+    test('supports the `thisArg` argument', function() {
+      var actual = _.uniq([1, 2, 1.5, 3, 2.5], function(num) {
+        return this.floor(num);
+      }, Math);
+
+      deepEqual(actual, [1, 2, 3]);
+    });
+
+    test('should distinguish between numbers and numeric strings', function() {
+      var expected = ['2', 2, Object('2'), Object(2)],
+          actual = _.uniq(expected);
+
+      deepEqual(actual, expected);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.uniqueId');
+
+  (function() {
+    test('should return a string value when not passing a prefix argument', function() {
+      equal(typeof _.uniqueId(), 'string');
+    });
+
+    test('should coerce the prefix argument to a string', function() {
+      var actual = [_.uniqueId(3), _.uniqueId(2), _.uniqueId(1)];
+      ok(/3\d+,2\d+,1\d+/.test(actual));
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash.where');
+
+  (function() {
+    var array = [
+      { 'a': 1 },
+      { 'a': 1 },
+      { 'a': 1, 'b': 2 },
+      { 'a': 2, 'b': 2 },
+      { 'a': 3 }
+    ];
+
+    test('should filter by properties', function() {
+      deepEqual(_.where(array, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]);
+      deepEqual(_.where(array, { 'a': 2 }), [{ 'a': 2, 'b': 2 }]);
+      deepEqual(_.where(array, { 'a': 3 }), [{ 'a': 3 }]);
+      deepEqual(_.where(array, { 'b': 1 }), []);
+      deepEqual(_.where(array, { 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]);
+      deepEqual(_.where(array, { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }]);
+    });
+
+    test('should not filter by inherited properties', function() {
+      function Foo() {}
+      Foo.prototype = { 'a': 2 };
+
+      var properties = new Foo;
+      properties.b = 2;
+      deepEqual(_.where(array, properties), [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }]);
+    });
+
+    test('should filter by problem JScript properties (test in IE < 9)', function() {
+      var collection = [shadowed];
+      deepEqual(_.where(collection, shadowed), [shadowed]);
+    });
+
+    test('should work with an object for `collection`', function() {
+      var collection = {
+        'x': { 'a': 1 },
+        'y': { 'a': 3 },
+        'z': { 'a': 1, 'b': 2 }
+      };
+
+      deepEqual(_.where(collection, { 'a': 1 }), [{ 'a': 1 }, { 'a': 1, 'b': 2 }]);
+    });
+
+    test('should return an empty array when passed an empty `properties` object', function() {
+      deepEqual(_.where(array, {}), []);
+    });
+
+    test('should deep compare `properties` values', function() {
+      var collection = [{ 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4 }],
+          expected = _.cloneDeep(collection);
+
+      deepEqual(_.where(collection, { 'a': { 'b': { 'c': 1 } } }), expected);
+    });
+
+    test('should search of arrays for values', function() {
+      var collection = [{ 'a': [1, 2] }],
+          expected = _.cloneDeep(collection);
+
+      deepEqual(_.where(collection, { 'a': [] }), []);
+      deepEqual(_.where(collection, { 'a': [2] }), expected);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...).shift');
+
+  (function() {
+    test('should remove the value at index `0` when length is `0` (test in IE 8 compatibility mode)', function() {
+      var wrapped = _({ '0': 1, 'length': 1 });
+      wrapped.shift();
+
+      deepEqual(wrapped.keys().value(), ['length']);
+      equal(wrapped.first(), undefined);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...).splice');
+
+  (function() {
+    test('should remove the value at index `0` when length is `0` (test in IE < 9, and in compatibility mode for IE9)', function() {
+      var wrapped = _({ '0': 1, 'length': 1 });
+      wrapped.splice(0, 1);
+
+      deepEqual(wrapped.keys().value(), ['length']);
+      equal(wrapped.first(), undefined);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...).toString');
+
+  (function() {
+    test('should return the `toString` result of the wrapped value', function() {
+      var wrapped = _([1, 2, 3]);
+      equal(String(wrapped), '1,2,3');
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...).valueOf');
+
+  (function() {
+    test('should return the `valueOf` result of the wrapped value', function() {
+      var wrapped = _(123);
+      equal(Number(wrapped), 123);
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...) methods that return wrapped values');
+
+  (function() {
+    var array = [1, 2, 3],
+        wrapped = _(array);
+
+    var funcs = [
+      'concat',
+      'splice'
+    ];
+
+    _.each(funcs, function(methodName) {
+      test('_.' + methodName + ' should return a wrapped value', function() {
+        ok(wrapped[methodName]() instanceof _);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...) methods that return unwrapped values');
+
+  (function() {
+    var array = [1, 2, 3],
+        wrapped = _(array);
+
+    var funcs = [
+      'clone',
+      'contains',
+      'every',
+      'find',
+      'first',
+      'has',
+      'isArguments',
+      'isArray',
+      'isBoolean',
+      'isDate',
+      'isElement',
+      'isEmpty',
+      'isEqual',
+      'isFinite',
+      'isFunction',
+      'isNaN',
+      'isNull',
+      'isNumber',
+      'isObject',
+      'isPlainObject',
+      'isRegExp',
+      'isString',
+      'isUndefined',
+      'join',
+      'last',
+      'pop',
+      'shift',
+      'reduce',
+      'reduceRight',
+      'some'
+    ];
+
+    _.each(funcs, function(methodName) {
+      test('_.' + methodName + ' should return an unwrapped value', function() {
+        var result = methodName == 'reduceRight'
+          ? wrapped[methodName](_.identity)
+          : wrapped[methodName]();
+
+        equal(result instanceof _, false);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash(...) methods capable of returning wrapped and unwrapped values');
+
+  (function() {
+    var array = [1, 2, 3],
+        wrapped = _(array);
+
+    var funcs = [
+      'first',
+      'last'
+    ];
+
+    _.each(funcs, function(methodName) {
+      test('_.' + methodName + ' should return an unwrapped value', function() {
+        equal(typeof wrapped[methodName](), 'number');
+      });
+
+      test('_.' + methodName + ' should return a wrapped value', function() {
+        ok(wrapped[methodName](1) instanceof _);
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  QUnit.module('lodash methods');
+
+  (function() {
+    test('should allow falsey arguments', function() {
+      var isExported = '_' in window,
+          oldDash = window._;
+
+      var returnArrays = [
+        'filter',
+        'invoke',
+        'map',
+        'pluck',
+        'reject',
+        'shuffle',
+        'sortBy',
+        'toArray',
+        'where'
+      ];
+
+      var funcs = _.without.apply(_, [_.functions(_)].concat([
+        '_',
+        '_each',
+        '_iteratorTemplate',
+        'after',
+        'bind',
+        'bindAll',
+        'compose',
+        'debounce',
+        'defer',
+        'delay',
+        'functions',
+        'memoize',
+        'once',
+        'partial',
+        'tap',
+        'throttle',
+        'wrap'
+      ]));
+
+      _.each(funcs, function(methodName) {
+        var actual = [],
+            expected = _.times(falsey.length, function() { return []; }),
+            func = _[methodName],
+            pass = true;
+
+        _.each(falsey, function(value, index) {
+          try {
+            actual.push(index ? func(value) : func());
+          } catch(e) {
+            pass = false;
+          }
+        });
+
+        if (methodName == 'noConflict') {
+          if (isExported) {
+            window._ = oldDash;
+          } else {
+            delete window._;
+          }
+        }
+        if (_.indexOf(returnArrays, methodName) > -1) {
+          deepEqual(actual, expected, '_.' + methodName + ' returns an array');
+        }
+        ok(pass, '_.' + methodName + ' allows falsey arguments');
+      });
+    });
+
+    test('should handle `null` `thisArg` arguments', function() {
+      var thisArg,
+          array = ['a'],
+          callback = function() { thisArg = this; },
+          expected = (function() { return this; }).call(null);
+
+      var funcs = [
+        'countBy',
+        'every',
+        'filter',
+        'find',
+        'forEach',
+        'forIn',
+        'forOwn',
+        'groupBy',
+        'map',
+        'max',
+        'min',
+        'omit',
+        'pick',
+        'reduce',
+        'reduceRight',
+        'reject',
+        'some',
+        'sortBy',
+        'sortedIndex',
+        'times',
+        'uniq'
+      ];
+
+      _.each(funcs, function(methodName) {
+        var func = _[methodName],
+            message = '_.' + methodName + ' handles `null` `thisArg` arguments';
+
+        thisArg = undefined;
+
+        if (/^reduce/.test(methodName)) {
+          func(array, callback, 0, null);
+        } else if (methodName == 'sortedIndex') {
+          func(array, 'a', callback, null);
+        } else if (methodName == 'times') {
+          func(1, callback, null);
+        } else {
+          func(array, callback, null);
+        }
+
+        if (expected === null) {
+          strictEqual(thisArg, null, message);
+        } else {
+          equal(thisArg, expected, message);
+        }
+      });
+    });
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  // configure QUnit and call `QUnit.start()` for Narwhal, Node.js, PhantomJS, Rhino, and RingoJS
+  if (!window.document || window.phantom) {
+    QUnit.config.noglobals = true;
+    QUnit.start();
+  }
+}(typeof global == 'object' && global || this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/LICENSE.txt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/LICENSE.txt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/LICENSE.txt	(revision 533)
@@ -0,0 +1,22 @@
+Copyright 2010-2013 Mathias Bynens <http://mathiasbynens.be/>
+Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
+Modified by John-David Dalton <http://allyoucanleet.com/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/README.md	(revision 533)
@@ -0,0 +1,136 @@
+# Benchmark.js <sup>v1.0.0</sup>
+[![build status](https://secure.travis-ci.org/bestiejs/benchmark.js.png)](http://travis-ci.org/bestiejs/benchmark.js)
+
+A [robust](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/ "Bulletproof JavaScript benchmarks") benchmarking library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>, supports high-resolution timers, and returns statistically significant results. As seen on [jsPerf](http://jsperf.com/).
+
+## Download
+
+ * [Development source](https://raw.github.com/bestiejs/benchmark.js/v1.0.0/benchmark.js)
+
+## Dive in
+
+Weâve got [API docs](http://benchmarkjs.com/docs) and [unit tests](http://benchmarkjs.com/tests).
+
+For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).
+
+## Support
+
+Benchmark.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-15, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.8, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
+
+## Installation and usage
+
+In a browser or Adobe AIR:
+
+```html
+<script src="benchmark.js"></script>
+```
+
+Optionally, expose Javaâs nanosecond timer by adding the `nano` applet to the `<body>`:
+
+```html
+<applet code="nano" archive="nano.jar"></applet>
+```
+
+Or enable Chromeâs microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
+
+    --enable-benchmarking
+
+Via [npm](http://npmjs.org/):
+
+```bash
+npm install benchmark
+```
+
+In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
+
+```js
+var Benchmark = require('benchmark');
+```
+
+Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
+
+```bash
+npm install microtime
+```
+
+In [RingoJS v0.7.0-](http://ringojs.org/):
+
+```js
+var Benchmark = require('benchmark').Benchmark;
+```
+
+In [Rhino](http://www.mozilla.org/rhino/):
+
+```js
+load('benchmark.js');
+```
+
+In an AMD loader like [RequireJS](http://requirejs.org/):
+
+```js
+require({
+  'paths': {
+    'benchmark': 'path/to/benchmark'
+  }
+},
+['benchmark'], function(Benchmark) {
+  console.log(Benchmark.version);
+});
+
+// or with platform.js
+// https://github.com/bestiejs/platform.js
+require({
+  'paths': {
+    'benchmark': 'path/to/benchmark',
+    'platform': 'path/to/platform'
+  }
+},
+['benchmark', 'platform'], function(Benchmark, platform) {
+  Benchmark.platform = platform;
+  console.log(Benchmark.platform.name);
+});
+```
+
+Usage example:
+
+```js
+var suite = new Benchmark.Suite;
+
+// add tests
+suite.add('RegExp#test', function() {
+  /o/.test('Hello World!');
+})
+.add('String#indexOf', function() {
+  'Hello World!'.indexOf('o') > -1;
+})
+// add listeners
+.on('cycle', function(event) {
+  console.log(String(event.target));
+})
+.on('complete', function() {
+  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
+})
+// run async
+.run({ 'async': true });
+
+// logs:
+// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
+// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
+// > Fastest is String#indexOf
+```
+
+## BestieJS
+
+Benchmark.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
+
+## Authors
+
+* [Mathias Bynens](http://mathiasbynens.be/)
+  [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")
+* [John-David Dalton](http://allyoucanleet.com/)
+  [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
+
+## Contributors
+
+* [Kit Cambridge](http://kitcambridge.github.com/)
+  [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/benchmark.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/benchmark.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/benchmark.js	(revision 533)
@@ -0,0 +1,3960 @@
+/*!
+ * Benchmark.js v1.0.0 <http://benchmarkjs.com/>
+ * Copyright 2010-2013 Mathias Bynens <http://mths.be/>
+ * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
+ * Modified by John-David Dalton <http://allyoucanleet.com/>
+ * Available under MIT license <http://mths.be/mit>
+ */
+;(function(window, undefined) {
+  'use strict';
+
+  /** Used to assign each benchmark an incrimented id */
+  var counter = 0;
+
+  /** Detect DOM document object */
+  var doc = isHostType(window, 'document') && document;
+
+  /** Detect free variable `define` */
+  var freeDefine = typeof define == 'function' &&
+    typeof define.amd == 'object' && define.amd && define;
+
+  /** Detect free variable `exports` */
+  var freeExports = typeof exports == 'object' && exports &&
+    (typeof global == 'object' && global && global == global.global && (window = global), exports);
+
+  /** Detect free variable `require` */
+  var freeRequire = typeof require == 'function' && require;
+
+  /** Used to store the `Object` built-in in case it's overwritten later */
+  var Object = window.Object;
+
+  /** Used to crawl all properties regardless of enumerability */
+  var getAllKeys = Object.getOwnPropertyNames;
+
+  /** Used to get property descriptors */
+  var getDescriptor = Object.getOwnPropertyDescriptor;
+
+  /** Used in case an object doesn't have its own method */
+  var hasOwnProperty = {}.hasOwnProperty;
+
+  /** Used to check if an object is extensible */
+  var isExtensible = Object.isExtensible || function() { return true; };
+
+  /** Used to access Wade Simmons' Node microtime module */
+  var microtimeObject = req('microtime');
+
+  /** Used to access the browser's high resolution timer */
+  var perfObject = isHostType(window, 'performance') && performance;
+
+  /** Used to call the browser's high resolution timer */
+  var perfName = perfObject && (
+    perfObject.now && 'now' ||
+    perfObject.webkitNow && 'webkitNow'
+  );
+
+  /** Used to access Node's high resolution timer */
+  var processObject = isHostType(window, 'process') && process;
+
+  /** Used to check if an own property is enumerable */
+  var propertyIsEnumerable = {}.propertyIsEnumerable;
+
+  /** Used to set property descriptors */
+  var setDescriptor = Object.defineProperty;
+
+  /** Used to resolve a value's internal [[Class]] */
+  var toString = {}.toString;
+
+  /** Used to prevent a `removeChild` memory leak in IE < 9 */
+  var trash = doc && doc.createElement('div');
+
+  /** Used to integrity check compiled tests */
+  var uid = 'uid' + (+new Date);
+
+  /** Used to avoid infinite recursion when methods call each other */
+  var calledBy = {};
+
+  /** Used to avoid hz of Infinity */
+  var divisors = {
+    '1': 4096,
+    '2': 512,
+    '3': 64,
+    '4': 8,
+    '5': 0
+  };
+
+  /**
+   * T-Distribution two-tailed critical values for 95% confidence
+   * http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm
+   */
+  var tTable = {
+    '1':  12.706,'2':  4.303, '3':  3.182, '4':  2.776, '5':  2.571, '6':  2.447,
+    '7':  2.365, '8':  2.306, '9':  2.262, '10': 2.228, '11': 2.201, '12': 2.179,
+    '13': 2.16,  '14': 2.145, '15': 2.131, '16': 2.12,  '17': 2.11,  '18': 2.101,
+    '19': 2.093, '20': 2.086, '21': 2.08,  '22': 2.074, '23': 2.069, '24': 2.064,
+    '25': 2.06,  '26': 2.056, '27': 2.052, '28': 2.048, '29': 2.045, '30': 2.042,
+    'infinity': 1.96
+  };
+
+  /**
+   * Critical Mann-Whitney U-values for 95% confidence
+   * http://www.saburchill.com/IBbiology/stats/003.html
+   */
+  var uTable = {
+    '5':  [0, 1, 2],
+    '6':  [1, 2, 3, 5],
+    '7':  [1, 3, 5, 6, 8],
+    '8':  [2, 4, 6, 8, 10, 13],
+    '9':  [2, 4, 7, 10, 12, 15, 17],
+    '10': [3, 5, 8, 11, 14, 17, 20, 23],
+    '11': [3, 6, 9, 13, 16, 19, 23, 26, 30],
+    '12': [4, 7, 11, 14, 18, 22, 26, 29, 33, 37],
+    '13': [4, 8, 12, 16, 20, 24, 28, 33, 37, 41, 45],
+    '14': [5, 9, 13, 17, 22, 26, 31, 36, 40, 45, 50, 55],
+    '15': [5, 10, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64],
+    '16': [6, 11, 15, 21, 26, 31, 37, 42, 47, 53, 59, 64, 70, 75],
+    '17': [6, 11, 17, 22, 28, 34, 39, 45, 51, 57, 63, 67, 75, 81, 87],
+    '18': [7, 12, 18, 24, 30, 36, 42, 48, 55, 61, 67, 74, 80, 86, 93, 99],
+    '19': [7, 13, 19, 25, 32, 38, 45, 52, 58, 65, 72, 78, 85, 92, 99, 106, 113],
+    '20': [8, 14, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90, 98, 105, 112, 119, 127],
+    '21': [8, 15, 22, 29, 36, 43, 50, 58, 65, 73, 80, 88, 96, 103, 111, 119, 126, 134, 142],
+    '22': [9, 16, 23, 30, 38, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 150, 158],
+    '23': [9, 17, 24, 32, 40, 48, 56, 64, 73, 81, 89, 98, 106, 115, 123, 132, 140, 149, 157, 166, 175],
+    '24': [10, 17, 25, 33, 42, 50, 59, 67, 76, 85, 94, 102, 111, 120, 129, 138, 147, 156, 165, 174, 183, 192],
+    '25': [10, 18, 27, 35, 44, 53, 62, 71, 80, 89, 98, 107, 117, 126, 135, 145, 154, 163, 173, 182, 192, 201, 211],
+    '26': [11, 19, 28, 37, 46, 55, 64, 74, 83, 93, 102, 112, 122, 132, 141, 151, 161, 171, 181, 191, 200, 210, 220, 230],
+    '27': [11, 20, 29, 38, 48, 57, 67, 77, 87, 97, 107, 118, 125, 138, 147, 158, 168, 178, 188, 199, 209, 219, 230, 240, 250],
+    '28': [12, 21, 30, 40, 50, 60, 70, 80, 90, 101, 111, 122, 132, 143, 154, 164, 175, 186, 196, 207, 218, 228, 239, 250, 261, 272],
+    '29': [13, 22, 32, 42, 52, 62, 73, 83, 94, 105, 116, 127, 138, 149, 160, 171, 182, 193, 204, 215, 226, 238, 249, 260, 271, 282, 294],
+    '30': [13, 23, 33, 43, 54, 65, 76, 87, 98, 109, 120, 131, 143, 154, 166, 177, 189, 200, 212, 223, 235, 247, 258, 270, 282, 293, 305, 317]
+  };
+
+  /**
+   * An object used to flag environments/features.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @type Object
+   */
+  var support = {};
+
+  (function() {
+
+    /**
+     * Detect Adobe AIR.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.air = isClassOf(window.runtime, 'ScriptBridgingProxyObject');
+
+    /**
+     * Detect if `arguments` objects have the correct internal [[Class]] value.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.argumentsClass = isClassOf(arguments, 'Arguments');
+
+    /**
+     * Detect if in a browser environment.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.browser = doc && isHostType(window, 'navigator');
+
+    /**
+     * Detect if strings support accessing characters by index.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.charByIndex =
+      // IE 8 supports indexes on string literals but not string objects
+      ('x'[0] + Object('x')[0]) == 'xx';
+
+    /**
+     * Detect if strings have indexes as own properties.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.charByOwnIndex =
+      // Narwhal, Rhino, RingoJS, IE 8, and Opera < 10.52 support indexes on
+      // strings but don't detect them as own properties
+      support.charByIndex && hasKey('x', '0');
+
+    /**
+     * Detect if Java is enabled/exposed.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.java = isClassOf(window.java, 'JavaPackage');
+
+    /**
+     * Detect if the Timers API exists.
+     *
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.timeout = isHostType(window, 'setTimeout') && isHostType(window, 'clearTimeout');
+
+    /**
+     * Detect if functions support decompilation.
+     *
+     * @name decompilation
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    try {
+      // Safari 2.x removes commas in object literals
+      // from Function#toString results
+      // http://webk.it/11609
+      // Firefox 3.6 and Opera 9.25 strip grouping
+      // parentheses from Function#toString results
+      // http://bugzil.la/559438
+      support.decompilation = Function(
+        'return (' + (function(x) { return { 'x': '' + (1 + x) + '', 'y': 0 }; }) + ')'
+      )()(0).x === '1';
+    } catch(e) {
+      support.decompilation = false;
+    }
+
+    /**
+     * Detect ES5+ property descriptor API.
+     *
+     * @name descriptors
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    try {
+      var o = {};
+      support.descriptors = (setDescriptor(o, o, o), 'value' in getDescriptor(o, o));
+    } catch(e) {
+      support.descriptors = false;
+    }
+
+    /**
+     * Detect ES5+ Object.getOwnPropertyNames().
+     *
+     * @name getAllKeys
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    try {
+      support.getAllKeys = /\bvalueOf\b/.test(getAllKeys(Object.prototype));
+    } catch(e) {
+      support.getAllKeys = false;
+    }
+
+    /**
+     * Detect if own properties are iterated before inherited properties (all but IE < 9).
+     *
+     * @name iteratesOwnLast
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    support.iteratesOwnFirst = (function() {
+      var props = [];
+      function ctor() { this.x = 1; }
+      ctor.prototype = { 'y': 1 };
+      for (var prop in new ctor) { props.push(prop); }
+      return props[0] == 'x';
+    }());
+
+    /**
+     * Detect if a node's [[Class]] is resolvable (all but IE < 9)
+     * and that the JS engine errors when attempting to coerce an object to a
+     * string without a `toString` property value of `typeof` "function".
+     *
+     * @name nodeClass
+     * @memberOf Benchmark.support
+     * @type Boolean
+     */
+    try {
+      support.nodeClass = ({ 'toString': 0 } + '', toString.call(doc || 0) != '[object Object]');
+    } catch(e) {
+      support.nodeClass = true;
+    }
+  }());
+
+  /**
+   * Timer object used by `clock()` and `Deferred#resolve`.
+   *
+   * @private
+   * @type Object
+   */
+  var timer = {
+
+   /**
+    * The timer namespace object or constructor.
+    *
+    * @private
+    * @memberOf timer
+    * @type Function|Object
+    */
+    'ns': Date,
+
+   /**
+    * Starts the deferred timer.
+    *
+    * @private
+    * @memberOf timer
+    * @param {Object} deferred The deferred instance.
+    */
+    'start': null, // lazy defined in `clock()`
+
+   /**
+    * Stops the deferred timer.
+    *
+    * @private
+    * @memberOf timer
+    * @param {Object} deferred The deferred instance.
+    */
+    'stop': null // lazy defined in `clock()`
+  };
+
+  /** Shortcut for inverse results */
+  var noArgumentsClass = !support.argumentsClass,
+      noCharByIndex = !support.charByIndex,
+      noCharByOwnIndex = !support.charByOwnIndex;
+
+  /** Math shortcuts */
+  var abs   = Math.abs,
+      floor = Math.floor,
+      log   = Math.log,
+      max   = Math.max,
+      min   = Math.min,
+      pow   = Math.pow,
+      sqrt  = Math.sqrt;
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The Benchmark constructor.
+   *
+   * @constructor
+   * @param {String} name A name to identify the benchmark.
+   * @param {Function|String} fn The test to benchmark.
+   * @param {Object} [options={}] Options object.
+   * @example
+   *
+   * // basic usage (the `new` operator is optional)
+   * var bench = new Benchmark(fn);
+   *
+   * // or using a name first
+   * var bench = new Benchmark('foo', fn);
+   *
+   * // or with options
+   * var bench = new Benchmark('foo', fn, {
+   *
+   *   // displayed by Benchmark#toString if `name` is not available
+   *   'id': 'xyz',
+   *
+   *   // called when the benchmark starts running
+   *   'onStart': onStart,
+   *
+   *   // called after each run cycle
+   *   'onCycle': onCycle,
+   *
+   *   // called when aborted
+   *   'onAbort': onAbort,
+   *
+   *   // called when a test errors
+   *   'onError': onError,
+   *
+   *   // called when reset
+   *   'onReset': onReset,
+   *
+   *   // called when the benchmark completes running
+   *   'onComplete': onComplete,
+   *
+   *   // compiled/called before the test loop
+   *   'setup': setup,
+   *
+   *   // compiled/called after the test loop
+   *   'teardown': teardown
+   * });
+   *
+   * // or name and options
+   * var bench = new Benchmark('foo', {
+   *
+   *   // a flag to indicate the benchmark is deferred
+   *   'defer': true,
+   *
+   *   // benchmark test function
+   *   'fn': function(deferred) {
+   *     // call resolve() when the deferred test is finished
+   *     deferred.resolve();
+   *   }
+   * });
+   *
+   * // or options only
+   * var bench = new Benchmark({
+   *
+   *   // benchmark name
+   *   'name': 'foo',
+   *
+   *   // benchmark test as a string
+   *   'fn': '[1,2,3,4].sort()'
+   * });
+   *
+   * // a test's `this` binding is set to the benchmark instance
+   * var bench = new Benchmark('foo', function() {
+   *   'My name is '.concat(this.name); // My name is foo
+   * });
+   */
+  function Benchmark(name, fn, options) {
+    var me = this;
+
+    // allow instance creation without the `new` operator
+    if (me == null || me.constructor != Benchmark) {
+      return new Benchmark(name, fn, options);
+    }
+    // juggle arguments
+    if (isClassOf(name, 'Object')) {
+      // 1 argument (options)
+      options = name;
+    }
+    else if (isClassOf(name, 'Function')) {
+      // 2 arguments (fn, options)
+      options = fn;
+      fn = name;
+    }
+    else if (isClassOf(fn, 'Object')) {
+      // 2 arguments (name, options)
+      options = fn;
+      fn = null;
+      me.name = name;
+    }
+    else {
+      // 3 arguments (name, fn [, options])
+      me.name = name;
+    }
+    setOptions(me, options);
+    me.id || (me.id = ++counter);
+    me.fn == null && (me.fn = fn);
+    me.stats = deepClone(me.stats);
+    me.times = deepClone(me.times);
+  }
+
+  /**
+   * The Deferred constructor.
+   *
+   * @constructor
+   * @memberOf Benchmark
+   * @param {Object} clone The cloned benchmark instance.
+   */
+  function Deferred(clone) {
+    var me = this;
+    if (me == null || me.constructor != Deferred) {
+      return new Deferred(clone);
+    }
+    me.benchmark = clone;
+    clock(me);
+  }
+
+  /**
+   * The Event constructor.
+   *
+   * @constructor
+   * @memberOf Benchmark
+   * @param {String|Object} type The event type.
+   */
+  function Event(type) {
+    var me = this;
+    return (me == null || me.constructor != Event)
+      ? new Event(type)
+      : (type instanceof Event)
+          ? type
+          : extend(me, { 'timeStamp': +new Date }, typeof type == 'string' ? { 'type': type } : type);
+  }
+
+  /**
+   * The Suite constructor.
+   *
+   * @constructor
+   * @memberOf Benchmark
+   * @param {String} name A name to identify the suite.
+   * @param {Object} [options={}] Options object.
+   * @example
+   *
+   * // basic usage (the `new` operator is optional)
+   * var suite = new Benchmark.Suite;
+   *
+   * // or using a name first
+   * var suite = new Benchmark.Suite('foo');
+   *
+   * // or with options
+   * var suite = new Benchmark.Suite('foo', {
+   *
+   *   // called when the suite starts running
+   *   'onStart': onStart,
+   *
+   *   // called between running benchmarks
+   *   'onCycle': onCycle,
+   *
+   *   // called when aborted
+   *   'onAbort': onAbort,
+   *
+   *   // called when a test errors
+   *   'onError': onError,
+   *
+   *   // called when reset
+   *   'onReset': onReset,
+   *
+   *   // called when the suite completes running
+   *   'onComplete': onComplete
+   * });
+   */
+  function Suite(name, options) {
+    var me = this;
+
+    // allow instance creation without the `new` operator
+    if (me == null || me.constructor != Suite) {
+      return new Suite(name, options);
+    }
+    // juggle arguments
+    if (isClassOf(name, 'Object')) {
+      // 1 argument (options)
+      options = name;
+    } else {
+      // 2 arguments (name [, options])
+      me.name = name;
+    }
+    setOptions(me, options);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Note: Some array methods have been implemented in plain JavaScript to avoid
+   * bugs in IE, Opera, Rhino, and Mobile Safari.
+   *
+   * IE compatibility mode and IE < 9 have buggy Array `shift()` and `splice()`
+   * functions that fail to remove the last element, `object[0]`, of
+   * array-like-objects even though the `length` property is set to `0`.
+   * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+   * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+   *
+   * In Opera < 9.50 and some older/beta Mobile Safari versions using `unshift()`
+   * generically to augment the `arguments` object will pave the value at index 0
+   * without incrimenting the other values's indexes.
+   * https://github.com/documentcloud/underscore/issues/9
+   *
+   * Rhino and environments it powers, like Narwhal and RingoJS, may have
+   * buggy Array `concat()`, `reverse()`, `shift()`, `slice()`, `splice()` and
+   * `unshift()` functions that make sparse arrays non-sparse by assigning the
+   * undefined indexes a value of undefined.
+   * https://github.com/mozilla/rhino/commit/702abfed3f8ca043b2636efd31c14ba7552603dd
+   */
+
+  /**
+   * Creates an array containing the elements of the host array followed by the
+   * elements of each argument in order.
+   *
+   * @memberOf Benchmark.Suite
+   * @returns {Array} The new array.
+   */
+  function concat() {
+    var value,
+        j = -1,
+        length = arguments.length,
+        result = slice.call(this),
+        index = result.length;
+
+    while (++j < length) {
+      value = arguments[j];
+      if (isClassOf(value, 'Array')) {
+        for (var k = 0, l = value.length; k < l; k++, index++) {
+          if (k in value) {
+            result[index] = value[k];
+          }
+        }
+      } else {
+        result[index++] = value;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Utility function used by `shift()`, `splice()`, and `unshift()`.
+   *
+   * @private
+   * @param {Number} start The index to start inserting elements.
+   * @param {Number} deleteCount The number of elements to delete from the insert point.
+   * @param {Array} elements The elements to insert.
+   * @returns {Array} An array of deleted elements.
+   */
+  function insert(start, deleteCount, elements) {
+    // `result` should have its length set to the `deleteCount`
+    // see https://bugs.ecmascript.org/show_bug.cgi?id=332
+    var deleteEnd = start + deleteCount,
+        elementCount = elements ? elements.length : 0,
+        index = start - 1,
+        length = start + elementCount,
+        object = this,
+        result = Array(deleteCount),
+        tail = slice.call(object, deleteEnd);
+
+    // delete elements from the array
+    while (++index < deleteEnd) {
+      if (index in object) {
+        result[index - start] = object[index];
+        delete object[index];
+      }
+    }
+    // insert elements
+    index = start - 1;
+    while (++index < length) {
+      object[index] = elements[index - start];
+    }
+    // append tail elements
+    start = index--;
+    length = max(0, (object.length >>> 0) - deleteCount + elementCount);
+    while (++index < length) {
+      if ((index - start) in tail) {
+        object[index] = tail[index - start];
+      } else if (index in object) {
+        delete object[index];
+      }
+    }
+    // delete excess elements
+    deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0;
+    while (deleteCount--) {
+      index = length + deleteCount;
+      if (index in object) {
+        delete object[index];
+      }
+    }
+    object.length = length;
+    return result;
+  }
+
+  /**
+   * Rearrange the host array's elements in reverse order.
+   *
+   * @memberOf Benchmark.Suite
+   * @returns {Array} The reversed array.
+   */
+  function reverse() {
+    var upperIndex,
+        value,
+        index = -1,
+        object = Object(this),
+        length = object.length >>> 0,
+        middle = floor(length / 2);
+
+    if (length > 1) {
+      while (++index < middle) {
+        upperIndex = length - index - 1;
+        value = upperIndex in object ? object[upperIndex] : uid;
+        if (index in object) {
+          object[upperIndex] = object[index];
+        } else {
+          delete object[upperIndex];
+        }
+        if (value != uid) {
+          object[index] = value;
+        } else {
+          delete object[index];
+        }
+      }
+    }
+    return object;
+  }
+
+  /**
+   * Removes the first element of the host array and returns it.
+   *
+   * @memberOf Benchmark.Suite
+   * @returns {Mixed} The first element of the array.
+   */
+  function shift() {
+    return insert.call(this, 0, 1)[0];
+  }
+
+  /**
+   * Creates an array of the host array's elements from the start index up to,
+   * but not including, the end index.
+   *
+   * @memberOf Benchmark.Suite
+   * @param {Number} start The starting index.
+   * @param {Number} end The end index.
+   * @returns {Array} The new array.
+   */
+  function slice(start, end) {
+    var index = -1,
+        object = Object(this),
+        length = object.length >>> 0,
+        result = [];
+
+    start = toInteger(start);
+    start = start < 0 ? max(length + start, 0) : min(start, length);
+    start--;
+    end = end == null ? length : toInteger(end);
+    end = end < 0 ? max(length + end, 0) : min(end, length);
+
+    while ((++index, ++start) < end) {
+      if (start in object) {
+        result[index] = object[start];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Allows removing a range of elements and/or inserting elements into the
+   * host array.
+   *
+   * @memberOf Benchmark.Suite
+   * @param {Number} start The start index.
+   * @param {Number} deleteCount The number of elements to delete.
+   * @param {Mixed} [val1, val2, ...] values to insert at the `start` index.
+   * @returns {Array} An array of removed elements.
+   */
+  function splice(start, deleteCount) {
+    var object = Object(this),
+        length = object.length >>> 0;
+
+    start = toInteger(start);
+    start = start < 0 ? max(length + start, 0) : min(start, length);
+
+    // support the de-facto SpiderMonkey extension
+    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice#Parameters
+    // https://bugs.ecmascript.org/show_bug.cgi?id=429
+    deleteCount = arguments.length == 1
+      ? length - start
+      : min(max(toInteger(deleteCount), 0), length - start);
+
+    return insert.call(object, start, deleteCount, slice.call(arguments, 2));
+  }
+
+  /**
+   * Converts the specified `value` to an integer.
+   *
+   * @private
+   * @param {Mixed} value The value to convert.
+   * @returns {Number} The resulting integer.
+   */
+  function toInteger(value) {
+    value = +value;
+    return value === 0 || !isFinite(value) ? value || 0 : value - (value % 1);
+  }
+
+  /**
+   * Appends arguments to the host array.
+   *
+   * @memberOf Benchmark.Suite
+   * @returns {Number} The new length.
+   */
+  function unshift() {
+    var object = Object(this);
+    insert.call(object, 0, 0, arguments);
+    return object.length;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * A generic `Function#bind` like method.
+   *
+   * @private
+   * @param {Function} fn The function to be bound to `thisArg`.
+   * @param {Mixed} thisArg The `this` binding for the given function.
+   * @returns {Function} The bound function.
+   */
+  function bind(fn, thisArg) {
+    return function() { fn.apply(thisArg, arguments); };
+  }
+
+  /**
+   * Creates a function from the given arguments string and body.
+   *
+   * @private
+   * @param {String} args The comma separated function arguments.
+   * @param {String} body The function body.
+   * @returns {Function} The new function.
+   */
+  function createFunction() {
+    // lazy define
+    createFunction = function(args, body) {
+      var result,
+          anchor = freeDefine ? define.amd : Benchmark,
+          prop = uid + 'createFunction';
+
+      runScript((freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '=function(' + args + '){' + body + '}');
+      result = anchor[prop];
+      delete anchor[prop];
+      return result;
+    };
+    // fix JaegerMonkey bug
+    // http://bugzil.la/639720
+    createFunction = support.browser && (createFunction('', 'return"' + uid + '"') || noop)() == uid ? createFunction : Function;
+    return createFunction.apply(null, arguments);
+  }
+
+  /**
+   * Delay the execution of a function based on the benchmark's `delay` property.
+   *
+   * @private
+   * @param {Object} bench The benchmark instance.
+   * @param {Object} fn The function to execute.
+   */
+  function delay(bench, fn) {
+    bench._timerId = setTimeout(fn, bench.delay * 1e3);
+  }
+
+  /**
+   * Destroys the given element.
+   *
+   * @private
+   * @param {Element} element The element to destroy.
+   */
+  function destroyElement(element) {
+    trash.appendChild(element);
+    trash.innerHTML = '';
+  }
+
+  /**
+   * Iterates over an object's properties, executing the `callback` for each.
+   * Callbacks may terminate the loop by explicitly returning `false`.
+   *
+   * @private
+   * @param {Object} object The object to iterate over.
+   * @param {Function} callback The function executed per own property.
+   * @param {Object} options The options object.
+   * @returns {Object} Returns the object iterated over.
+   */
+  function forProps() {
+    var forShadowed,
+        skipSeen,
+        forArgs = true,
+        shadowed = ['constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf'];
+
+    (function(enumFlag, key) {
+      // must use a non-native constructor to catch the Safari 2 issue
+      function Klass() { this.valueOf = 0; };
+      Klass.prototype.valueOf = 0;
+      // check various for-in bugs
+      for (key in new Klass) {
+        enumFlag += key == 'valueOf' ? 1 : 0;
+      }
+      // check if `arguments` objects have non-enumerable indexes
+      for (key in arguments) {
+        key == '0' && (forArgs = false);
+      }
+      // Safari 2 iterates over shadowed properties twice
+      // http://replay.waybackmachine.org/20090428222941/http://tobielangel.com/2007/1/29/for-in-loop-broken-in-safari/
+      skipSeen = enumFlag == 2;
+      // IE < 9 incorrectly makes an object's properties non-enumerable if they have
+      // the same name as other non-enumerable properties in its prototype chain.
+      forShadowed = !enumFlag;
+    }(0));
+
+    // lazy define
+    forProps = function(object, callback, options) {
+      options || (options = {});
+
+      var result = object;
+      object = Object(object);
+
+      var ctor,
+          key,
+          keys,
+          skipCtor,
+          done = !result,
+          which = options.which,
+          allFlag = which == 'all',
+          index = -1,
+          iteratee = object,
+          length = object.length,
+          ownFlag = allFlag || which == 'own',
+          seen = {},
+          skipProto = isClassOf(object, 'Function'),
+          thisArg = options.bind;
+
+      if (thisArg !== undefined) {
+        callback = bind(callback, thisArg);
+      }
+      // iterate all properties
+      if (allFlag && support.getAllKeys) {
+        for (index = 0, keys = getAllKeys(object), length = keys.length; index < length; index++) {
+          key = keys[index];
+          if (callback(object[key], key, object) === false) {
+            break;
+          }
+        }
+      }
+      // else iterate only enumerable properties
+      else {
+        for (key in object) {
+          // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+          // (if the prototype or a property on the prototype has been set)
+          // incorrectly set a function's `prototype` property [[Enumerable]] value
+          // to `true`. Because of this we standardize on skipping the `prototype`
+          // property of functions regardless of their [[Enumerable]] value.
+          if ((done =
+              !(skipProto && key == 'prototype') &&
+              !(skipSeen && (hasKey(seen, key) || !(seen[key] = true))) &&
+              (!ownFlag || ownFlag && hasKey(object, key)) &&
+              callback(object[key], key, object) === false)) {
+            break;
+          }
+        }
+        // in IE < 9 strings don't support accessing characters by index
+        if (!done && (forArgs && isArguments(object) ||
+            ((noCharByIndex || noCharByOwnIndex) && isClassOf(object, 'String') &&
+              (iteratee = noCharByIndex ? object.split('') : object)))) {
+          while (++index < length) {
+            if ((done =
+                callback(iteratee[index], String(index), object) === false)) {
+              break;
+            }
+          }
+        }
+        if (!done && forShadowed) {
+          // Because IE < 9 can't set the `[[Enumerable]]` attribute of an existing
+          // property and the `constructor` property of a prototype defaults to
+          // non-enumerable, we manually skip the `constructor` property when we
+          // think we are iterating over a `prototype` object.
+          ctor = object.constructor;
+          skipCtor = ctor && ctor.prototype && ctor.prototype.constructor === ctor;
+          for (index = 0; index < 7; index++) {
+            key = shadowed[index];
+            if (!(skipCtor && key == 'constructor') &&
+                hasKey(object, key) &&
+                callback(object[key], key, object) === false) {
+              break;
+            }
+          }
+        }
+      }
+      return result;
+    };
+    return forProps.apply(null, arguments);
+  }
+
+  /**
+   * Gets the name of the first argument from a function's source.
+   *
+   * @private
+   * @param {Function} fn The function.
+   * @returns {String} The argument name.
+   */
+  function getFirstArgument(fn) {
+    return (!hasKey(fn, 'toString') &&
+      (/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || '';
+  }
+
+  /**
+   * Computes the geometric mean (log-average) of a sample.
+   * See http://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms.
+   *
+   * @private
+   * @param {Array} sample The sample.
+   * @returns {Number} The geometric mean.
+   */
+  function getGeometricMean(sample) {
+    return pow(Math.E, reduce(sample, function(sum, x) {
+      return sum + log(x);
+    }) / sample.length) || 0;
+  }
+
+  /**
+   * Computes the arithmetic mean of a sample.
+   *
+   * @private
+   * @param {Array} sample The sample.
+   * @returns {Number} The mean.
+   */
+  function getMean(sample) {
+    return (reduce(sample, function(sum, x) {
+      return sum + x;
+    }) / sample.length) || 0;
+  }
+
+  /**
+   * Gets the source code of a function.
+   *
+   * @private
+   * @param {Function} fn The function.
+   * @param {String} altSource A string used when a function's source code is unretrievable.
+   * @returns {String} The function's source code.
+   */
+  function getSource(fn, altSource) {
+    var result = altSource;
+    if (isStringable(fn)) {
+      result = String(fn);
+    } else if (support.decompilation) {
+      // escape the `{` for Firefox 1
+      result = (/^[^{]+\{([\s\S]*)\}\s*$/.exec(fn) || 0)[1];
+    }
+    // trim string
+    result = (result || '').replace(/^\s+|\s+$/g, '');
+
+    // detect strings containing only the "use strict" directive
+    return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
+      ? ''
+      : result;
+  }
+
+  /**
+   * Checks if a value is an `arguments` object.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the value is an `arguments` object, else `false`.
+   */
+  function isArguments() {
+    // lazy define
+    isArguments = function(value) {
+      return toString.call(value) == '[object Arguments]';
+    };
+    if (noArgumentsClass) {
+      isArguments = function(value) {
+        return hasKey(value, 'callee') &&
+          !(propertyIsEnumerable && propertyIsEnumerable.call(value, 'callee'));
+      };
+    }
+    return isArguments(arguments[0]);
+  }
+
+  /**
+   * Checks if an object is of the specified class.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @param {String} name The name of the class.
+   * @returns {Boolean} Returns `true` if the value is of the specified class, else `false`.
+   */
+  function isClassOf(value, name) {
+    return value != null && toString.call(value) == '[object ' + name + ']';
+  }
+
+  /**
+   * Host objects can return type values that are different from their actual
+   * data type. The objects we are concerned with usually return non-primitive
+   * types of object, function, or unknown.
+   *
+   * @private
+   * @param {Mixed} object The owner of the property.
+   * @param {String} property The property to check.
+   * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
+   */
+  function isHostType(object, property) {
+    var type = object != null ? typeof object[property] : 'number';
+    return !/^(?:boolean|number|string|undefined)$/.test(type) &&
+      (type == 'object' ? !!object[property] : true);
+  }
+
+  /**
+   * Checks if a given `value` is an object created by the `Object` constructor
+   * assuming objects created by the `Object` constructor have no inherited
+   * enumerable properties and that there are no `Object.prototype` extensions.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, else `false`.
+   */
+  function isPlainObject(value) {
+    // avoid non-objects and false positives for `arguments` objects in IE < 9
+    var result = false;
+    if (!(value && typeof value == 'object') || isArguments(value)) {
+      return result;
+    }
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings.
+    // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
+    var ctor = value.constructor;
+    if ((support.nodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
+        (!isClassOf(ctor, 'Function') || ctor instanceof ctor)) {
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      if (support.iteratesOwnFirst) {
+        forProps(value, function(subValue, subKey) {
+          result = subKey;
+        });
+        return result === false || hasKey(value, result);
+      }
+      // IE < 9 iterates inherited properties before own properties. If the first
+      // iterated property is an object's own property then there are no inherited
+      // enumerable properties.
+      forProps(value, function(subValue, subKey) {
+        result = !hasKey(value, subKey);
+        return false;
+      });
+      return result === false;
+    }
+    return result;
+  }
+
+  /**
+   * Checks if a value can be safely coerced to a string.
+   *
+   * @private
+   * @param {Mixed} value The value to check.
+   * @returns {Boolean} Returns `true` if the value can be coerced, else `false`.
+   */
+  function isStringable(value) {
+    return hasKey(value, 'toString') || isClassOf(value, 'String');
+  }
+
+  /**
+   * Wraps a function and passes `this` to the original function as the
+   * first argument.
+   *
+   * @private
+   * @param {Function} fn The function to be wrapped.
+   * @returns {Function} The new function.
+   */
+  function methodize(fn) {
+    return function() {
+      var args = [this];
+      args.push.apply(args, arguments);
+      return fn.apply(null, args);
+    };
+  }
+
+  /**
+   * A no-operation function.
+   *
+   * @private
+   */
+  function noop() {
+    // no operation performed
+  }
+
+  /**
+   * A wrapper around require() to suppress `module missing` errors.
+   *
+   * @private
+   * @param {String} id The module id.
+   * @returns {Mixed} The exported module or `null`.
+   */
+  function req(id) {
+    try {
+      var result = freeExports && freeRequire(id);
+    } catch(e) { }
+    return result || null;
+  }
+
+  /**
+   * Runs a snippet of JavaScript via script injection.
+   *
+   * @private
+   * @param {String} code The code to run.
+   */
+  function runScript(code) {
+    var anchor = freeDefine ? define.amd : Benchmark,
+        script = doc.createElement('script'),
+        sibling = doc.getElementsByTagName('script')[0],
+        parent = sibling.parentNode,
+        prop = uid + 'runScript',
+        prefix = '(' + (freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '||function(){})();';
+
+    // Firefox 2.0.0.2 cannot use script injection as intended because it executes
+    // asynchronously, but that's OK because script injection is only used to avoid
+    // the previously commented JaegerMonkey bug.
+    try {
+      // remove the inserted script *before* running the code to avoid differences
+      // in the expected script element count/order of the document.
+      script.appendChild(doc.createTextNode(prefix + code));
+      anchor[prop] = function() { destroyElement(script); };
+    } catch(e) {
+      parent = parent.cloneNode(false);
+      sibling = null;
+      script.text = code;
+    }
+    parent.insertBefore(script, sibling);
+    delete anchor[prop];
+  }
+
+  /**
+   * A helper function for setting options/event handlers.
+   *
+   * @private
+   * @param {Object} bench The benchmark instance.
+   * @param {Object} [options={}] Options object.
+   */
+  function setOptions(bench, options) {
+    options = extend({}, bench.constructor.options, options);
+    bench.options = forOwn(options, function(value, key) {
+      if (value != null) {
+        // add event listeners
+        if (/^on[A-Z]/.test(key)) {
+          forEach(key.split(' '), function(key) {
+            bench.on(key.slice(2).toLowerCase(), value);
+          });
+        } else if (!hasKey(bench, key)) {
+          bench[key] = deepClone(value);
+        }
+      }
+    });
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Handles cycling/completing the deferred benchmark.
+   *
+   * @memberOf Benchmark.Deferred
+   */
+  function resolve() {
+    var me = this,
+        clone = me.benchmark,
+        bench = clone._original;
+
+    if (bench.aborted) {
+      // cycle() -> clone cycle/complete event -> compute()'s invoked bench.run() cycle/complete
+      me.teardown();
+      clone.running = false;
+      cycle(me);
+    }
+    else if (++me.cycles < clone.count) {
+      // continue the test loop
+      if (support.timeout) {
+        // use setTimeout to avoid a call stack overflow if called recursively
+        setTimeout(function() { clone.compiled.call(me, timer); }, 0);
+      } else {
+        clone.compiled.call(me, timer);
+      }
+    }
+    else {
+      timer.stop(me);
+      me.teardown();
+      delay(clone, function() { cycle(me); });
+    }
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * A deep clone utility.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Mixed} value The value to clone.
+   * @returns {Mixed} The cloned value.
+   */
+  function deepClone(value) {
+    var accessor,
+        circular,
+        clone,
+        ctor,
+        descriptor,
+        extensible,
+        key,
+        length,
+        markerKey,
+        parent,
+        result,
+        source,
+        subIndex,
+        data = { 'value': value },
+        index = 0,
+        marked = [],
+        queue = { 'length': 0 },
+        unmarked = [];
+
+    /**
+     * An easily detectable decorator for cloned values.
+     */
+    function Marker(object) {
+      this.raw = object;
+    }
+
+    /**
+     * The callback used by `forProps()`.
+     */
+    function forPropsCallback(subValue, subKey) {
+      // exit early to avoid cloning the marker
+      if (subValue && subValue.constructor == Marker) {
+        return;
+      }
+      // add objects to the queue
+      if (subValue === Object(subValue)) {
+        queue[queue.length++] = { 'key': subKey, 'parent': clone, 'source': value };
+      }
+      // assign non-objects
+      else {
+        try {
+          // will throw an error in strict mode if the property is read-only
+          clone[subKey] = subValue;
+        } catch(e) { }
+      }
+    }
+
+    /**
+     * Gets an available marker key for the given object.
+     */
+    function getMarkerKey(object) {
+      // avoid collisions with existing keys
+      var result = uid;
+      while (object[result] && object[result].constructor != Marker) {
+        result += 1;
+      }
+      return result;
+    }
+
+    do {
+      key = data.key;
+      parent = data.parent;
+      source = data.source;
+      clone = value = source ? source[key] : data.value;
+      accessor = circular = descriptor = false;
+
+      // create a basic clone to filter out functions, DOM elements, and
+      // other non `Object` objects
+      if (value === Object(value)) {
+        // use custom deep clone function if available
+        if (isClassOf(value.deepClone, 'Function')) {
+          clone = value.deepClone();
+        } else {
+          ctor = value.constructor;
+          switch (toString.call(value)) {
+            case '[object Array]':
+              clone = new ctor(value.length);
+              break;
+
+            case '[object Boolean]':
+              clone = new ctor(value == true);
+              break;
+
+            case '[object Date]':
+              clone = new ctor(+value);
+              break;
+
+            case '[object Object]':
+              isPlainObject(value) && (clone = {});
+              break;
+
+            case '[object Number]':
+            case '[object String]':
+              clone = new ctor(value);
+              break;
+
+            case '[object RegExp]':
+              clone = ctor(value.source,
+                (value.global     ? 'g' : '') +
+                (value.ignoreCase ? 'i' : '') +
+                (value.multiline  ? 'm' : ''));
+          }
+        }
+        // continue clone if `value` doesn't have an accessor descriptor
+        // http://es5.github.com/#x8.10.1
+        if (clone && clone != value &&
+            !(descriptor = source && support.descriptors && getDescriptor(source, key),
+              accessor = descriptor && (descriptor.get || descriptor.set))) {
+          // use an existing clone (circular reference)
+          if ((extensible = isExtensible(value))) {
+            markerKey = getMarkerKey(value);
+            if (value[markerKey]) {
+              circular = clone = value[markerKey].raw;
+            }
+          } else {
+            // for frozen/sealed objects
+            for (subIndex = 0, length = unmarked.length; subIndex < length; subIndex++) {
+              data = unmarked[subIndex];
+              if (data.object === value) {
+                circular = clone = data.clone;
+                break;
+              }
+            }
+          }
+          if (!circular) {
+            // mark object to allow quickly detecting circular references and tie it to its clone
+            if (extensible) {
+              value[markerKey] = new Marker(clone);
+              marked.push({ 'key': markerKey, 'object': value });
+            } else {
+              // for frozen/sealed objects
+              unmarked.push({ 'clone': clone, 'object': value });
+            }
+            // iterate over object properties
+            forProps(value, forPropsCallback, { 'which': 'all' });
+          }
+        }
+      }
+      if (parent) {
+        // for custom property descriptors
+        if (accessor || (descriptor && !(descriptor.configurable && descriptor.enumerable && descriptor.writable))) {
+          if ('value' in descriptor) {
+            descriptor.value = clone;
+          }
+          setDescriptor(parent, key, descriptor);
+        }
+        // for default property descriptors
+        else {
+          parent[key] = clone;
+        }
+      } else {
+        result = clone;
+      }
+    } while ((data = queue[index++]));
+
+    // remove markers
+    for (index = 0, length = marked.length; index < length; index++) {
+      data = marked[index];
+      delete data.object[data.key];
+    }
+    return result;
+  }
+
+  /**
+   * An iteration utility for arrays and objects.
+   * Callbacks may terminate the loop by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array|Object} object The object to iterate over.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} thisArg The `this` binding for the callback.
+   * @returns {Array|Object} Returns the object iterated over.
+   */
+  function each(object, callback, thisArg) {
+    var result = object;
+    object = Object(object);
+
+    var fn = callback,
+        index = -1,
+        length = object.length,
+        isSnapshot = !!(object.snapshotItem && (length = object.snapshotLength)),
+        isSplittable = (noCharByIndex || noCharByOwnIndex) && isClassOf(object, 'String'),
+        isConvertable = isSnapshot || isSplittable || 'item' in object,
+        origObject = object;
+
+    // in Opera < 10.5 `hasKey(object, 'length')` returns `false` for NodeLists
+    if (length === length >>> 0) {
+      if (isConvertable) {
+        // the third argument of the callback is the original non-array object
+        callback = function(value, index) {
+          return fn.call(this, value, index, origObject);
+        };
+        // in IE < 9 strings don't support accessing characters by index
+        if (isSplittable) {
+          object = object.split('');
+        } else {
+          object = [];
+          while (++index < length) {
+            // in Safari 2 `index in object` is always `false` for NodeLists
+            object[index] = isSnapshot ? result.snapshotItem(index) : result[index];
+          }
+        }
+      }
+      forEach(object, callback, thisArg);
+    } else {
+      forOwn(object, callback, thisArg);
+    }
+    return result;
+  }
+
+  /**
+   * Copies enumerable properties from the source(s) object to the destination object.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Object} destination The destination object.
+   * @param {Object} [source={}] The source object.
+   * @returns {Object} The destination object.
+   */
+  function extend(destination, source) {
+    // Chrome < 14 incorrectly sets `destination` to `undefined` when we `delete arguments[0]`
+    // http://code.google.com/p/v8/issues/detail?id=839
+    var result = destination;
+    delete arguments[0];
+
+    forEach(arguments, function(source) {
+      forProps(source, function(value, key) {
+        result[key] = value;
+      });
+    });
+    return result;
+  }
+
+  /**
+   * A generic `Array#filter` like method.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} array The array to iterate over.
+   * @param {Function|String} callback The function/alias called per iteration.
+   * @param {Mixed} thisArg The `this` binding for the callback.
+   * @returns {Array} A new array of values that passed callback filter.
+   * @example
+   *
+   * // get odd numbers
+   * Benchmark.filter([1, 2, 3, 4, 5], function(n) {
+   *   return n % 2;
+   * }); // -> [1, 3, 5];
+   *
+   * // get fastest benchmarks
+   * Benchmark.filter(benches, 'fastest');
+   *
+   * // get slowest benchmarks
+   * Benchmark.filter(benches, 'slowest');
+   *
+   * // get benchmarks that completed without erroring
+   * Benchmark.filter(benches, 'successful');
+   */
+  function filter(array, callback, thisArg) {
+    var result;
+
+    if (callback == 'successful') {
+      // callback to exclude those that are errored, unrun, or have hz of Infinity
+      callback = function(bench) { return bench.cycles && isFinite(bench.hz); };
+    }
+    else if (callback == 'fastest' || callback == 'slowest') {
+      // get successful, sort by period + margin of error, and filter fastest/slowest
+      result = filter(array, 'successful').sort(function(a, b) {
+        a = a.stats; b = b.stats;
+        return (a.mean + a.moe > b.mean + b.moe ? 1 : -1) * (callback == 'fastest' ? 1 : -1);
+      });
+      result = filter(result, function(bench) {
+        return result[0].compare(bench) == 0;
+      });
+    }
+    return result || reduce(array, function(result, value, index) {
+      return callback.call(thisArg, value, index, array) ? (result.push(value), result) : result;
+    }, []);
+  }
+
+  /**
+   * A generic `Array#forEach` like method.
+   * Callbacks may terminate the loop by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} array The array to iterate over.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} thisArg The `this` binding for the callback.
+   * @returns {Array} Returns the array iterated over.
+   */
+  function forEach(array, callback, thisArg) {
+    var index = -1,
+        length = (array = Object(array)).length >>> 0;
+
+    if (thisArg !== undefined) {
+      callback = bind(callback, thisArg);
+    }
+    while (++index < length) {
+      if (index in array &&
+          callback(array[index], index, array) === false) {
+        break;
+      }
+    }
+    return array;
+  }
+
+  /**
+   * Iterates over an object's own properties, executing the `callback` for each.
+   * Callbacks may terminate the loop by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Object} object The object to iterate over.
+   * @param {Function} callback The function executed per own property.
+   * @param {Mixed} thisArg The `this` binding for the callback.
+   * @returns {Object} Returns the object iterated over.
+   */
+  function forOwn(object, callback, thisArg) {
+    return forProps(object, callback, { 'bind': thisArg, 'which': 'own' });
+  }
+
+  /**
+   * Converts a number to a more readable comma-separated string representation.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Number} number The number to convert.
+   * @returns {String} The more readable string representation.
+   */
+  function formatNumber(number) {
+    number = String(number).split('.');
+    return number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') +
+      (number[1] ? '.' + number[1] : '');
+  }
+
+  /**
+   * Checks if an object has the specified key as a direct property.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Object} object The object to check.
+   * @param {String} key The key to check for.
+   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+   */
+  function hasKey() {
+    // lazy define for worst case fallback (not as accurate)
+    hasKey = function(object, key) {
+      var parent = object != null && (object.constructor || Object).prototype;
+      return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);
+    };
+    // for modern browsers
+    if (isClassOf(hasOwnProperty, 'Function')) {
+      hasKey = function(object, key) {
+        return object != null && hasOwnProperty.call(object, key);
+      };
+    }
+    // for Safari 2
+    else if ({}.__proto__ == Object.prototype) {
+      hasKey = function(object, key) {
+        var result = false;
+        if (object != null) {
+          object = Object(object);
+          object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];
+        }
+        return result;
+      };
+    }
+    return hasKey.apply(this, arguments);
+  }
+
+  /**
+   * A generic `Array#indexOf` like method.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} array The array to iterate over.
+   * @param {Mixed} value The value to search for.
+   * @param {Number} [fromIndex=0] The index to start searching from.
+   * @returns {Number} The index of the matched value or `-1`.
+   */
+  function indexOf(array, value, fromIndex) {
+    var index = toInteger(fromIndex),
+        length = (array = Object(array)).length >>> 0;
+
+    index = (index < 0 ? max(0, length + index) : index) - 1;
+    while (++index < length) {
+      if (index in array && value === array[index]) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Modify a string by replacing named tokens with matching object property values.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {String} string The string to modify.
+   * @param {Object} object The template object.
+   * @returns {String} The modified string.
+   */
+  function interpolate(string, object) {
+    forOwn(object, function(value, key) {
+      // escape regexp special characters in `key`
+      string = string.replace(
+        RegExp('#\\{' + key.replace(/([.*+?^${}()|[\]\\])/g, '\\$1') + '\\}', 'g'),
+        value.replace(/\$/g, '$$$$')
+      );
+    });
+    return string;
+  }
+
+  /**
+   * Invokes a method on all items in an array.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} benches Array of benchmarks to iterate over.
+   * @param {String|Object} name The name of the method to invoke OR options object.
+   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+   * @returns {Array} A new array of values returned from each method invoked.
+   * @example
+   *
+   * // invoke `reset` on all benchmarks
+   * Benchmark.invoke(benches, 'reset');
+   *
+   * // invoke `emit` with arguments
+   * Benchmark.invoke(benches, 'emit', 'complete', listener);
+   *
+   * // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks
+   * Benchmark.invoke(benches, {
+   *
+   *   // invoke the `run` method
+   *   'name': 'run',
+   *
+   *   // pass a single argument
+   *   'args': true,
+   *
+   *   // treat as queue, removing benchmarks from front of `benches` until empty
+   *   'queued': true,
+   *
+   *   // called before any benchmarks have been invoked.
+   *   'onStart': onStart,
+   *
+   *   // called between invoking benchmarks
+   *   'onCycle': onCycle,
+   *
+   *   // called after all benchmarks have been invoked.
+   *   'onComplete': onComplete
+   * });
+   */
+  function invoke(benches, name) {
+    var args,
+        bench,
+        queued,
+        index = -1,
+        eventProps = { 'currentTarget': benches },
+        options = { 'onStart': noop, 'onCycle': noop, 'onComplete': noop },
+        result = map(benches, function(bench) { return bench; });
+
+    /**
+     * Invokes the method of the current object and if synchronous, fetches the next.
+     */
+    function execute() {
+      var listeners,
+          async = isAsync(bench);
+
+      if (async) {
+        // use `getNext` as the first listener
+        bench.on('complete', getNext);
+        listeners = bench.events.complete;
+        listeners.splice(0, 0, listeners.pop());
+      }
+      // execute method
+      result[index] = isClassOf(bench && bench[name], 'Function') ? bench[name].apply(bench, args) : undefined;
+      // if synchronous return true until finished
+      return !async && getNext();
+    }
+
+    /**
+     * Fetches the next bench or executes `onComplete` callback.
+     */
+    function getNext(event) {
+      var cycleEvent,
+          last = bench,
+          async = isAsync(last);
+
+      if (async) {
+        last.off('complete', getNext);
+        last.emit('complete');
+      }
+      // emit "cycle" event
+      eventProps.type = 'cycle';
+      eventProps.target = last;
+      cycleEvent = Event(eventProps);
+      options.onCycle.call(benches, cycleEvent);
+
+      // choose next benchmark if not exiting early
+      if (!cycleEvent.aborted && raiseIndex() !== false) {
+        bench = queued ? benches[0] : result[index];
+        if (isAsync(bench)) {
+          delay(bench, execute);
+        }
+        else if (async) {
+          // resume execution if previously asynchronous but now synchronous
+          while (execute()) { }
+        }
+        else {
+          // continue synchronous execution
+          return true;
+        }
+      } else {
+        // emit "complete" event
+        eventProps.type = 'complete';
+        options.onComplete.call(benches, Event(eventProps));
+      }
+      // When used as a listener `event.aborted = true` will cancel the rest of
+      // the "complete" listeners because they were already called above and when
+      // used as part of `getNext` the `return false` will exit the execution while-loop.
+      if (event) {
+        event.aborted = true;
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * Checks if invoking `Benchmark#run` with asynchronous cycles.
+     */
+    function isAsync(object) {
+      // avoid using `instanceof` here because of IE memory leak issues with host objects
+      var async = args[0] && args[0].async;
+      return Object(object).constructor == Benchmark && name == 'run' &&
+        ((async == null ? object.options.async : async) && support.timeout || object.defer);
+    }
+
+    /**
+     * Raises `index` to the next defined index or returns `false`.
+     */
+    function raiseIndex() {
+      var length = result.length;
+      if (queued) {
+        // if queued remove the previous bench and subsequent skipped non-entries
+        do {
+          ++index > 0 && shift.call(benches);
+        } while ((length = benches.length) && !('0' in benches));
+      }
+      else {
+        while (++index < length && !(index in result)) { }
+      }
+      // if we reached the last index then return `false`
+      return (queued ? length : index < length) ? index : (index = false);
+    }
+
+    // juggle arguments
+    if (isClassOf(name, 'String')) {
+      // 2 arguments (array, name)
+      args = slice.call(arguments, 2);
+    } else {
+      // 2 arguments (array, options)
+      options = extend(options, name);
+      name = options.name;
+      args = isClassOf(args = 'args' in options ? options.args : [], 'Array') ? args : [args];
+      queued = options.queued;
+    }
+
+    // start iterating over the array
+    if (raiseIndex() !== false) {
+      // emit "start" event
+      bench = result[index];
+      eventProps.type = 'start';
+      eventProps.target = bench;
+      options.onStart.call(benches, Event(eventProps));
+
+      // end early if the suite was aborted in an "onStart" listener
+      if (benches.aborted && benches.constructor == Suite && name == 'run') {
+        // emit "cycle" event
+        eventProps.type = 'cycle';
+        options.onCycle.call(benches, Event(eventProps));
+        // emit "complete" event
+        eventProps.type = 'complete';
+        options.onComplete.call(benches, Event(eventProps));
+      }
+      // else start
+      else {
+        if (isAsync(bench)) {
+          delay(bench, execute);
+        } else {
+          while (execute()) { }
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates a string of joined array values or object key-value pairs.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array|Object} object The object to operate on.
+   * @param {String} [separator1=','] The separator used between key-value pairs.
+   * @param {String} [separator2=': '] The separator used between keys and values.
+   * @returns {String} The joined result.
+   */
+  function join(object, separator1, separator2) {
+    var result = [],
+        length = (object = Object(object)).length,
+        arrayLike = length === length >>> 0;
+
+    separator2 || (separator2 = ': ');
+    each(object, function(value, key) {
+      result.push(arrayLike ? value : key + separator2 + value);
+    });
+    return result.join(separator1 || ',');
+  }
+
+  /**
+   * A generic `Array#map` like method.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} array The array to iterate over.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} thisArg The `this` binding for the callback.
+   * @returns {Array} A new array of values returned by the callback.
+   */
+  function map(array, callback, thisArg) {
+    return reduce(array, function(result, value, index) {
+      result[index] = callback.call(thisArg, value, index, array);
+      return result;
+    }, Array(Object(array).length >>> 0));
+  }
+
+  /**
+   * Retrieves the value of a specified property from all items in an array.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} array The array to iterate over.
+   * @param {String} property The property to pluck.
+   * @returns {Array} A new array of property values.
+   */
+  function pluck(array, property) {
+    return map(array, function(object) {
+      return object == null ? undefined : object[property];
+    });
+  }
+
+  /**
+   * A generic `Array#reduce` like method.
+   *
+   * @static
+   * @memberOf Benchmark
+   * @param {Array} array The array to iterate over.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} accumulator Initial value of the accumulator.
+   * @returns {Mixed} The accumulator.
+   */
+  function reduce(array, callback, accumulator) {
+    var noaccum = arguments.length < 3;
+    forEach(array, function(value, index) {
+      accumulator = noaccum ? (noaccum = false, value) : callback(accumulator, value, index, array);
+    });
+    return accumulator;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Aborts all benchmarks in the suite.
+   *
+   * @name abort
+   * @memberOf Benchmark.Suite
+   * @returns {Object} The suite instance.
+   */
+  function abortSuite() {
+    var event,
+        me = this,
+        resetting = calledBy.resetSuite;
+
+    if (me.running) {
+      event = Event('abort');
+      me.emit(event);
+      if (!event.cancelled || resetting) {
+        // avoid infinite recursion
+        calledBy.abortSuite = true;
+        me.reset();
+        delete calledBy.abortSuite;
+
+        if (!resetting) {
+          me.aborted = true;
+          invoke(me, 'abort');
+        }
+      }
+    }
+    return me;
+  }
+
+  /**
+   * Adds a test to the benchmark suite.
+   *
+   * @memberOf Benchmark.Suite
+   * @param {String} name A name to identify the benchmark.
+   * @param {Function|String} fn The test to benchmark.
+   * @param {Object} [options={}] Options object.
+   * @returns {Object} The benchmark instance.
+   * @example
+   *
+   * // basic usage
+   * suite.add(fn);
+   *
+   * // or using a name first
+   * suite.add('foo', fn);
+   *
+   * // or with options
+   * suite.add('foo', fn, {
+   *   'onCycle': onCycle,
+   *   'onComplete': onComplete
+   * });
+   *
+   * // or name and options
+   * suite.add('foo', {
+   *   'fn': fn,
+   *   'onCycle': onCycle,
+   *   'onComplete': onComplete
+   * });
+   *
+   * // or options only
+   * suite.add({
+   *   'name': 'foo',
+   *   'fn': fn,
+   *   'onCycle': onCycle,
+   *   'onComplete': onComplete
+   * });
+   */
+  function add(name, fn, options) {
+    var me = this,
+        bench = Benchmark(name, fn, options),
+        event = Event({ 'type': 'add', 'target': bench });
+
+    if (me.emit(event), !event.cancelled) {
+      me.push(bench);
+    }
+    return me;
+  }
+
+  /**
+   * Creates a new suite with cloned benchmarks.
+   *
+   * @name clone
+   * @memberOf Benchmark.Suite
+   * @param {Object} options Options object to overwrite cloned options.
+   * @returns {Object} The new suite instance.
+   */
+  function cloneSuite(options) {
+    var me = this,
+        result = new me.constructor(extend({}, me.options, options));
+
+    // copy own properties
+    forOwn(me, function(value, key) {
+      if (!hasKey(result, key)) {
+        result[key] = value && isClassOf(value.clone, 'Function')
+          ? value.clone()
+          : deepClone(value);
+      }
+    });
+    return result;
+  }
+
+  /**
+   * An `Array#filter` like method.
+   *
+   * @name filter
+   * @memberOf Benchmark.Suite
+   * @param {Function|String} callback The function/alias called per iteration.
+   * @returns {Object} A new suite of benchmarks that passed callback filter.
+   */
+  function filterSuite(callback) {
+    var me = this,
+        result = new me.constructor;
+
+    result.push.apply(result, filter(me, callback));
+    return result;
+  }
+
+  /**
+   * Resets all benchmarks in the suite.
+   *
+   * @name reset
+   * @memberOf Benchmark.Suite
+   * @returns {Object} The suite instance.
+   */
+  function resetSuite() {
+    var event,
+        me = this,
+        aborting = calledBy.abortSuite;
+
+    if (me.running && !aborting) {
+      // no worries, `resetSuite()` is called within `abortSuite()`
+      calledBy.resetSuite = true;
+      me.abort();
+      delete calledBy.resetSuite;
+    }
+    // reset if the state has changed
+    else if ((me.aborted || me.running) &&
+        (me.emit(event = Event('reset')), !event.cancelled)) {
+      me.running = false;
+      if (!aborting) {
+        invoke(me, 'reset');
+      }
+    }
+    return me;
+  }
+
+  /**
+   * Runs the suite.
+   *
+   * @name run
+   * @memberOf Benchmark.Suite
+   * @param {Object} [options={}] Options object.
+   * @returns {Object} The suite instance.
+   * @example
+   *
+   * // basic usage
+   * suite.run();
+   *
+   * // or with options
+   * suite.run({ 'async': true, 'queued': true });
+   */
+  function runSuite(options) {
+    var me = this;
+
+    me.reset();
+    me.running = true;
+    options || (options = {});
+
+    invoke(me, {
+      'name': 'run',
+      'args': options,
+      'queued': options.queued,
+      'onStart': function(event) {
+        me.emit(event);
+      },
+      'onCycle': function(event) {
+        var bench = event.target;
+        if (bench.error) {
+          me.emit({ 'type': 'error', 'target': bench });
+        }
+        me.emit(event);
+        event.aborted = me.aborted;
+      },
+      'onComplete': function(event) {
+        me.score = getGeometricMean(map(me, function(bench) {
+          return bench.reference / (bench.times.period * 1e6);
+        })) || 0;
+
+        me.running = false;
+        me.emit(event);
+      }
+    });
+    return me;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Executes all registered listeners of the specified event type.
+   *
+   * @memberOf Benchmark, Benchmark.Suite
+   * @param {String|Object} type The event type or object.
+   * @returns {Mixed} Returns the return value of the last listener executed.
+   */
+  function emit(type) {
+    var listeners,
+        me = this,
+        event = Event(type),
+        events = me.events,
+        args = (arguments[0] = event, arguments);
+
+    event.currentTarget || (event.currentTarget = me);
+    event.target || (event.target = me);
+    delete event.result;
+
+    if (events && (listeners = hasKey(events, event.type) && events[event.type])) {
+      forEach(listeners.slice(), function(listener) {
+        if ((event.result = listener.apply(me, args)) === false) {
+          event.cancelled = true;
+        }
+        return !event.aborted;
+      });
+    }
+    return event.result;
+  }
+
+  /**
+   * Returns an array of event listeners for a given type that can be manipulated
+   * to add or remove listeners.
+   *
+   * @memberOf Benchmark, Benchmark.Suite
+   * @param {String} type The event type.
+   * @returns {Array} The listeners array.
+   */
+  function listeners(type) {
+    var me = this,
+        events = me.events || (me.events = {});
+
+    return hasKey(events, type) ? events[type] : (events[type] = []);
+  }
+
+  /**
+   * Unregisters a listener for the specified event type(s),
+   * or unregisters all listeners for the specified event type(s),
+   * or unregisters all listeners for all event types.
+   *
+   * @memberOf Benchmark, Benchmark.Suite
+   * @param {String} [type] The event type.
+   * @param {Function} [listener] The function to unregister.
+   * @returns {Object} The benchmark instance.
+   * @example
+   *
+   * // unregister a listener for an event type
+   * bench.off('cycle', listener);
+   *
+   * // unregister a listener for multiple event types
+   * bench.off('start cycle', listener);
+   *
+   * // unregister all listeners for an event type
+   * bench.off('cycle');
+   *
+   * // unregister all listeners for multiple event types
+   * bench.off('start cycle complete');
+   *
+   * // unregister all listeners for all event types
+   * bench.off();
+   */
+  function off(type, listener) {
+    var me = this,
+        events = me.events;
+
+    events && each(type ? type.split(' ') : events, function(listeners, type) {
+      var index;
+      if (typeof listeners == 'string') {
+        type = listeners;
+        listeners = hasKey(events, type) && events[type];
+      }
+      if (listeners) {
+        if (listener) {
+          index = indexOf(listeners, listener);
+          if (index > -1) {
+            listeners.splice(index, 1);
+          }
+        } else {
+          listeners.length = 0;
+        }
+      }
+    });
+    return me;
+  }
+
+  /**
+   * Registers a listener for the specified event type(s).
+   *
+   * @memberOf Benchmark, Benchmark.Suite
+   * @param {String} type The event type.
+   * @param {Function} listener The function to register.
+   * @returns {Object} The benchmark instance.
+   * @example
+   *
+   * // register a listener for an event type
+   * bench.on('cycle', listener);
+   *
+   * // register a listener for multiple event types
+   * bench.on('start cycle', listener);
+   */
+  function on(type, listener) {
+    var me = this,
+        events = me.events || (me.events = {});
+
+    forEach(type.split(' '), function(type) {
+      (hasKey(events, type)
+        ? events[type]
+        : (events[type] = [])
+      ).push(listener);
+    });
+    return me;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Aborts the benchmark without recording times.
+   *
+   * @memberOf Benchmark
+   * @returns {Object} The benchmark instance.
+   */
+  function abort() {
+    var event,
+        me = this,
+        resetting = calledBy.reset;
+
+    if (me.running) {
+      event = Event('abort');
+      me.emit(event);
+      if (!event.cancelled || resetting) {
+        // avoid infinite recursion
+        calledBy.abort = true;
+        me.reset();
+        delete calledBy.abort;
+
+        if (support.timeout) {
+          clearTimeout(me._timerId);
+          delete me._timerId;
+        }
+        if (!resetting) {
+          me.aborted = true;
+          me.running = false;
+        }
+      }
+    }
+    return me;
+  }
+
+  /**
+   * Creates a new benchmark using the same test and options.
+   *
+   * @memberOf Benchmark
+   * @param {Object} options Options object to overwrite cloned options.
+   * @returns {Object} The new benchmark instance.
+   * @example
+   *
+   * var bizarro = bench.clone({
+   *   'name': 'doppelganger'
+   * });
+   */
+  function clone(options) {
+    var me = this,
+        result = new me.constructor(extend({}, me, options));
+
+    // correct the `options` object
+    result.options = extend({}, me.options, options);
+
+    // copy own custom properties
+    forOwn(me, function(value, key) {
+      if (!hasKey(result, key)) {
+        result[key] = deepClone(value);
+      }
+    });
+    return result;
+  }
+
+  /**
+   * Determines if a benchmark is faster than another.
+   *
+   * @memberOf Benchmark
+   * @param {Object} other The benchmark to compare.
+   * @returns {Number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate.
+   */
+  function compare(other) {
+    var critical,
+        zStat,
+        me = this,
+        sample1 = me.stats.sample,
+        sample2 = other.stats.sample,
+        size1 = sample1.length,
+        size2 = sample2.length,
+        maxSize = max(size1, size2),
+        minSize = min(size1, size2),
+        u1 = getU(sample1, sample2),
+        u2 = getU(sample2, sample1),
+        u = min(u1, u2);
+
+    function getScore(xA, sampleB) {
+      return reduce(sampleB, function(total, xB) {
+        return total + (xB > xA ? 0 : xB < xA ? 1 : 0.5);
+      }, 0);
+    }
+
+    function getU(sampleA, sampleB) {
+      return reduce(sampleA, function(total, xA) {
+        return total + getScore(xA, sampleB);
+      }, 0);
+    }
+
+    function getZ(u) {
+      return (u - ((size1 * size2) / 2)) / sqrt((size1 * size2 * (size1 + size2 + 1)) / 12);
+    }
+
+    // exit early if comparing the same benchmark
+    if (me == other) {
+      return 0;
+    }
+    // reject the null hyphothesis the two samples come from the
+    // same population (i.e. have the same median) if...
+    if (size1 + size2 > 30) {
+      // ...the z-stat is greater than 1.96 or less than -1.96
+      // http://www.statisticslectures.com/topics/mannwhitneyu/
+      zStat = getZ(u);
+      return abs(zStat) > 1.96 ? (zStat > 0 ? -1 : 1) : 0;
+    }
+    // ...the U value is less than or equal the critical U value
+    // http://www.geoib.com/mann-whitney-u-test.html
+    critical = maxSize < 5 || minSize < 3 ? 0 : uTable[maxSize][minSize - 3];
+    return u <= critical ? (u == u1 ? 1 : -1) : 0;
+  }
+
+  /**
+   * Reset properties and abort if running.
+   *
+   * @memberOf Benchmark
+   * @returns {Object} The benchmark instance.
+   */
+  function reset() {
+    var data,
+        event,
+        me = this,
+        index = 0,
+        changes = { 'length': 0 },
+        queue = { 'length': 0 };
+
+    if (me.running && !calledBy.abort) {
+      // no worries, `reset()` is called within `abort()`
+      calledBy.reset = true;
+      me.abort();
+      delete calledBy.reset;
+    }
+    else {
+      // a non-recursive solution to check if properties have changed
+      // http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4
+      data = { 'destination': me, 'source': extend({}, me.constructor.prototype, me.options) };
+      do {
+        forOwn(data.source, function(value, key) {
+          var changed,
+              destination = data.destination,
+              currValue = destination[key];
+
+          if (value && typeof value == 'object') {
+            if (isClassOf(value, 'Array')) {
+              // check if an array value has changed to a non-array value
+              if (!isClassOf(currValue, 'Array')) {
+                changed = currValue = [];
+              }
+              // or has changed its length
+              if (currValue.length != value.length) {
+                changed = currValue = currValue.slice(0, value.length);
+                currValue.length = value.length;
+              }
+            }
+            // check if an object has changed to a non-object value
+            else if (!currValue || typeof currValue != 'object') {
+              changed = currValue = {};
+            }
+            // register a changed object
+            if (changed) {
+              changes[changes.length++] = { 'destination': destination, 'key': key, 'value': currValue };
+            }
+            queue[queue.length++] = { 'destination': currValue, 'source': value };
+          }
+          // register a changed primitive
+          else if (value !== currValue && !(value == null || isClassOf(value, 'Function'))) {
+            changes[changes.length++] = { 'destination': destination, 'key': key, 'value': value };
+          }
+        });
+      }
+      while ((data = queue[index++]));
+
+      // if changed emit the `reset` event and if it isn't cancelled reset the benchmark
+      if (changes.length && (me.emit(event = Event('reset')), !event.cancelled)) {
+        forEach(changes, function(data) {
+          data.destination[data.key] = data.value;
+        });
+      }
+    }
+    return me;
+  }
+
+  /**
+   * Displays relevant benchmark information when coerced to a string.
+   *
+   * @name toString
+   * @memberOf Benchmark
+   * @returns {String} A string representation of the benchmark instance.
+   */
+  function toStringBench() {
+    var me = this,
+        error = me.error,
+        hz = me.hz,
+        id = me.id,
+        stats = me.stats,
+        size = stats.sample.length,
+        pm = support.java ? '+/-' : '\xb1',
+        result = me.name || (isNaN(id) ? id : '<Test #' + id + '>');
+
+    if (error) {
+      result += ': ' + join(error);
+    } else {
+      result += ' x ' + formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm +
+        stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)';
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Clocks the time taken to execute a test per cycle (secs).
+   *
+   * @private
+   * @param {Object} bench The benchmark instance.
+   * @returns {Number} The time taken.
+   */
+  function clock() {
+    var applet,
+        options = Benchmark.options,
+        template = { 'begin': 's$=new n$', 'end': 'r$=(new n$-s$)/1e3', 'uid': uid },
+        timers = [{ 'ns': timer.ns, 'res': max(0.0015, getRes('ms')), 'unit': 'ms' }];
+
+    // lazy define for hi-res timers
+    clock = function(clone) {
+      var deferred;
+      if (clone instanceof Deferred) {
+        deferred = clone;
+        clone = deferred.benchmark;
+      }
+
+      var bench = clone._original,
+          fn = bench.fn,
+          fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '',
+          stringable = isStringable(fn);
+
+      var source = {
+        'setup': getSource(bench.setup, preprocess('m$.setup()')),
+        'fn': getSource(fn, preprocess('m$.fn(' + fnArg + ')')),
+        'fnArg': fnArg,
+        'teardown': getSource(bench.teardown, preprocess('m$.teardown()'))
+      };
+
+      var count = bench.count = clone.count,
+          decompilable = support.decompilation || stringable,
+          id = bench.id,
+          isEmpty = !(source.fn || stringable),
+          name = bench.name || (typeof id == 'number' ? '<Test #' + id + '>' : id),
+          ns = timer.ns,
+          result = 0;
+
+      // init `minTime` if needed
+      clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime);
+
+      // repair nanosecond timer
+      // (some Chrome builds erase the `ns` variable after millions of executions)
+      if (applet) {
+        try {
+          ns.nanoTime();
+        } catch(e) {
+          // use non-element to avoid issues with libs that augment them
+          ns = timer.ns = new applet.Packages.nano;
+        }
+      }
+
+      // Compile in setup/teardown functions and the test loop.
+      // Create a new compiled test, instead of using the cached `bench.compiled`,
+      // to avoid potential engine optimizations enabled over the life of the test.
+      var compiled = bench.compiled = createFunction(preprocess('t$'), interpolate(
+        preprocess(deferred
+          ? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' +
+            // when `deferred.cycles` is `0` then...
+            'if(!d$.cycles){' +
+            // set `deferred.fn`
+            'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' +
+            // set `deferred.teardown`
+            'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' +
+            // execute the benchmark's `setup`
+            'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' +
+            // start timer
+            't$.start(d$);' +
+            // execute `deferred.fn` and return a dummy object
+            '}d$.fn();return{}'
+
+          : 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count,n$=t$.ns;#{setup}\n#{begin};' +
+            'while(i$--){#{fn}\n}#{end};#{teardown}\nreturn{elapsed:r$,uid:"#{uid}"}'),
+        source
+      ));
+
+      try {
+        if (isEmpty) {
+          // Firefox may remove dead code from Function#toString results
+          // http://bugzil.la/536085
+          throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
+        }
+        else if (!deferred) {
+          // pretest to determine if compiled code is exits early, usually by a
+          // rogue `return` statement, by checking for a return object with the uid
+          bench.count = 1;
+          compiled = (compiled.call(bench, timer) || {}).uid == uid && compiled;
+          bench.count = count;
+        }
+      } catch(e) {
+        compiled = null;
+        clone.error = e || new Error(String(e));
+        bench.count = count;
+      }
+      // fallback when a test exits early or errors during pretest
+      if (decompilable && !compiled && !deferred && !isEmpty) {
+        compiled = createFunction(preprocess('t$'), interpolate(
+          preprocess(
+            (clone.error && !stringable
+              ? 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count'
+              : 'function f$(){#{fn}\n}var r$,s$,m$=this,i$=m$.count'
+            ) +
+            ',n$=t$.ns;#{setup}\n#{begin};m$.f$=f$;while(i$--){m$.f$()}#{end};' +
+            'delete m$.f$;#{teardown}\nreturn{elapsed:r$}'
+          ),
+          source
+        ));
+
+        try {
+          // pretest one more time to check for errors
+          bench.count = 1;
+          compiled.call(bench, timer);
+          bench.compiled = compiled;
+          bench.count = count;
+          delete clone.error;
+        }
+        catch(e) {
+          bench.count = count;
+          if (clone.error) {
+            compiled = null;
+          } else {
+            bench.compiled = compiled;
+            clone.error = e || new Error(String(e));
+          }
+        }
+      }
+      // assign `compiled` to `clone` before calling in case a deferred benchmark
+      // immediately calls `deferred.resolve()`
+      clone.compiled = compiled;
+      // if no errors run the full test loop
+      if (!clone.error) {
+        result = compiled.call(deferred || bench, timer).elapsed;
+      }
+      return result;
+    };
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Gets the current timer's minimum resolution (secs).
+     */
+    function getRes(unit) {
+      var measured,
+          begin,
+          count = 30,
+          divisor = 1e3,
+          ns = timer.ns,
+          sample = [];
+
+      // get average smallest measurable time
+      while (count--) {
+        if (unit == 'us') {
+          divisor = 1e6;
+          if (ns.stop) {
+            ns.start();
+            while (!(measured = ns.microseconds())) { }
+          } else if (ns[perfName]) {
+            divisor = 1e3;
+            measured = Function('n', 'var r,s=n.' + perfName + '();while(!(r=n.' + perfName + '()-s)){};return r')(ns);
+          } else {
+            begin = ns();
+            while (!(measured = ns() - begin)) { }
+          }
+        }
+        else if (unit == 'ns') {
+          divisor = 1e9;
+          if (ns.nanoTime) {
+            begin = ns.nanoTime();
+            while (!(measured = ns.nanoTime() - begin)) { }
+          } else {
+            begin = (begin = ns())[0] + (begin[1] / divisor);
+            while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) { }
+            divisor = 1;
+          }
+        }
+        else {
+          begin = new ns;
+          while (!(measured = new ns - begin)) { }
+        }
+        // check for broken timers (nanoTime may have issues)
+        // http://alivebutsleepy.srnet.cz/unreliable-system-nanotime/
+        if (measured > 0) {
+          sample.push(measured);
+        } else {
+          sample.push(Infinity);
+          break;
+        }
+      }
+      // convert to seconds
+      return getMean(sample) / divisor;
+    }
+
+    /**
+     * Replaces all occurrences of `$` with a unique number and
+     * template tokens with content.
+     */
+    function preprocess(code) {
+      return interpolate(code, template).replace(/\$/g, /\d+/.exec(uid));
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    // detect nanosecond support from a Java applet
+    each(doc && doc.applets || [], function(element) {
+      return !(timer.ns = applet = 'nanoTime' in element && element);
+    });
+
+    // check type in case Safari returns an object instead of a number
+    try {
+      if (typeof timer.ns.nanoTime() == 'number') {
+        timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });
+      }
+    } catch(e) { }
+
+    // detect Chrome's microsecond timer:
+    // enable benchmarking via the --enable-benchmarking command
+    // line switch in at least Chrome 7 to use chrome.Interval
+    try {
+      if ((timer.ns = new (window.chrome || window.chromium).Interval)) {
+        timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });
+      }
+    } catch(e) { }
+
+    // detect `performance.now` microsecond resolution timer
+    if ((timer.ns = perfName && perfObject)) {
+      timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });
+    }
+
+    // detect Node's nanosecond resolution timer available in Node >= 0.8
+    if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') {
+      timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });
+    }
+
+    // detect Wade Simmons' Node microtime module
+    if (microtimeObject && typeof (timer.ns = microtimeObject.now) == 'function') {
+      timers.push({ 'ns': timer.ns,  'res': getRes('us'), 'unit': 'us' });
+    }
+
+    // pick timer with highest resolution
+    timer = reduce(timers, function(timer, other) {
+      return other.res < timer.res ? other : timer;
+    });
+
+    // remove unused applet
+    if (timer.unit != 'ns' && applet) {
+      applet = destroyElement(applet);
+    }
+    // error if there are no working timers
+    if (timer.res == Infinity) {
+      throw new Error('Benchmark.js was unable to find a working timer.');
+    }
+    // use API of chosen timer
+    if (timer.unit == 'ns') {
+      if (timer.ns.nanoTime) {
+        extend(template, {
+          'begin': 's$=n$.nanoTime()',
+          'end': 'r$=(n$.nanoTime()-s$)/1e9'
+        });
+      } else {
+        extend(template, {
+          'begin': 's$=n$()',
+          'end': 'r$=n$(s$);r$=r$[0]+(r$[1]/1e9)'
+        });
+      }
+    }
+    else if (timer.unit == 'us') {
+      if (timer.ns.stop) {
+        extend(template, {
+          'begin': 's$=n$.start()',
+          'end': 'r$=n$.microseconds()/1e6'
+        });
+      } else if (perfName) {
+        extend(template, {
+          'begin': 's$=n$.' + perfName + '()',
+          'end': 'r$=(n$.' + perfName + '()-s$)/1e3'
+        });
+      } else {
+        extend(template, {
+          'begin': 's$=n$()',
+          'end': 'r$=(n$()-s$)/1e6'
+        });
+      }
+    }
+
+    // define `timer` methods
+    timer.start = createFunction(preprocess('o$'),
+      preprocess('var n$=this.ns,#{begin};o$.elapsed=0;o$.timeStamp=s$'));
+
+    timer.stop = createFunction(preprocess('o$'),
+      preprocess('var n$=this.ns,s$=o$.timeStamp,#{end};o$.elapsed=r$'));
+
+    // resolve time span required to achieve a percent uncertainty of at most 1%
+    // http://spiff.rit.edu/classes/phys273/uncert/uncert.html
+    options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05));
+    return clock.apply(null, arguments);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Computes stats on benchmark results.
+   *
+   * @private
+   * @param {Object} bench The benchmark instance.
+   * @param {Object} options The options object.
+   */
+  function compute(bench, options) {
+    options || (options = {});
+
+    var async = options.async,
+        elapsed = 0,
+        initCount = bench.initCount,
+        minSamples = bench.minSamples,
+        queue = [],
+        sample = bench.stats.sample;
+
+    /**
+     * Adds a clone to the queue.
+     */
+    function enqueue() {
+      queue.push(bench.clone({
+        '_original': bench,
+        'events': {
+          'abort': [update],
+          'cycle': [update],
+          'error': [update],
+          'start': [update]
+        }
+      }));
+    }
+
+    /**
+     * Updates the clone/original benchmarks to keep their data in sync.
+     */
+    function update(event) {
+      var clone = this,
+          type = event.type;
+
+      if (bench.running) {
+        if (type == 'start') {
+          // Note: `clone.minTime` prop is inited in `clock()`
+          clone.count = bench.initCount;
+        }
+        else {
+          if (type == 'error') {
+            bench.error = clone.error;
+          }
+          if (type == 'abort') {
+            bench.abort();
+            bench.emit('cycle');
+          } else {
+            event.currentTarget = event.target = bench;
+            bench.emit(event);
+          }
+        }
+      } else if (bench.aborted) {
+        // clear abort listeners to avoid triggering bench's abort/cycle again
+        clone.events.abort.length = 0;
+        clone.abort();
+      }
+    }
+
+    /**
+     * Determines if more clones should be queued or if cycling should stop.
+     */
+    function evaluate(event) {
+      var critical,
+          df,
+          mean,
+          moe,
+          rme,
+          sd,
+          sem,
+          variance,
+          clone = event.target,
+          done = bench.aborted,
+          now = +new Date,
+          size = sample.push(clone.times.period),
+          maxedOut = size >= minSamples && (elapsed += now - clone.times.timeStamp) / 1e3 > bench.maxTime,
+          times = bench.times,
+          varOf = function(sum, x) { return sum + pow(x - mean, 2); };
+
+      // exit early for aborted or unclockable tests
+      if (done || clone.hz == Infinity) {
+        maxedOut = !(size = sample.length = queue.length = 0);
+      }
+
+      if (!done) {
+        // sample mean (estimate of the population mean)
+        mean = getMean(sample);
+        // sample variance (estimate of the population variance)
+        variance = reduce(sample, varOf, 0) / (size - 1) || 0;
+        // sample standard deviation (estimate of the population standard deviation)
+        sd = sqrt(variance);
+        // standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean)
+        sem = sd / sqrt(size);
+        // degrees of freedom
+        df = size - 1;
+        // critical value
+        critical = tTable[Math.round(df) || 1] || tTable.infinity;
+        // margin of error
+        moe = sem * critical;
+        // relative margin of error
+        rme = (moe / mean) * 100 || 0;
+
+        extend(bench.stats, {
+          'deviation': sd,
+          'mean': mean,
+          'moe': moe,
+          'rme': rme,
+          'sem': sem,
+          'variance': variance
+        });
+
+        // Abort the cycle loop when the minimum sample size has been collected
+        // and the elapsed time exceeds the maximum time allowed per benchmark.
+        // We don't count cycle delays toward the max time because delays may be
+        // increased by browsers that clamp timeouts for inactive tabs.
+        // https://developer.mozilla.org/en/window.setTimeout#Inactive_tabs
+        if (maxedOut) {
+          // reset the `initCount` in case the benchmark is rerun
+          bench.initCount = initCount;
+          bench.running = false;
+          done = true;
+          times.elapsed = (now - times.timeStamp) / 1e3;
+        }
+        if (bench.hz != Infinity) {
+          bench.hz = 1 / mean;
+          times.cycle = mean * bench.count;
+          times.period = mean;
+        }
+      }
+      // if time permits, increase sample size to reduce the margin of error
+      if (queue.length < 2 && !maxedOut) {
+        enqueue();
+      }
+      // abort the invoke cycle when done
+      event.aborted = done;
+    }
+
+    // init queue and begin
+    enqueue();
+    invoke(queue, {
+      'name': 'run',
+      'args': { 'async': async },
+      'queued': true,
+      'onCycle': evaluate,
+      'onComplete': function() { bench.emit('complete'); }
+    });
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Cycles a benchmark until a run `count` can be established.
+   *
+   * @private
+   * @param {Object} clone The cloned benchmark instance.
+   * @param {Object} options The options object.
+   */
+  function cycle(clone, options) {
+    options || (options = {});
+
+    var deferred;
+    if (clone instanceof Deferred) {
+      deferred = clone;
+      clone = clone.benchmark;
+    }
+
+    var clocked,
+        cycles,
+        divisor,
+        event,
+        minTime,
+        period,
+        async = options.async,
+        bench = clone._original,
+        count = clone.count,
+        times = clone.times;
+
+    // continue, if not aborted between cycles
+    if (clone.running) {
+      // `minTime` is set to `Benchmark.options.minTime` in `clock()`
+      cycles = ++clone.cycles;
+      clocked = deferred ? deferred.elapsed : clock(clone);
+      minTime = clone.minTime;
+
+      if (cycles > bench.cycles) {
+        bench.cycles = cycles;
+      }
+      if (clone.error) {
+        event = Event('error');
+        event.message = clone.error;
+        clone.emit(event);
+        if (!event.cancelled) {
+          clone.abort();
+        }
+      }
+    }
+
+    // continue, if not errored
+    if (clone.running) {
+      // time taken to complete last test cycle
+      bench.times.cycle = times.cycle = clocked;
+      // seconds per operation
+      period = bench.times.period = times.period = clocked / count;
+      // ops per second
+      bench.hz = clone.hz = 1 / period;
+      // avoid working our way up to this next time
+      bench.initCount = clone.initCount = count;
+      // do we need to do another cycle?
+      clone.running = clocked < minTime;
+
+      if (clone.running) {
+        // tests may clock at `0` when `initCount` is a small number,
+        // to avoid that we set its count to something a bit higher
+        if (!clocked && (divisor = divisors[clone.cycles]) != null) {
+          count = floor(4e6 / divisor);
+        }
+        // calculate how many more iterations it will take to achive the `minTime`
+        if (count <= clone.count) {
+          count += Math.ceil((minTime - clocked) / period);
+        }
+        clone.running = count != Infinity;
+      }
+    }
+    // should we exit early?
+    event = Event('cycle');
+    clone.emit(event);
+    if (event.aborted) {
+      clone.abort();
+    }
+    // figure out what to do next
+    if (clone.running) {
+      // start a new cycle
+      clone.count = count;
+      if (deferred) {
+        clone.compiled.call(deferred, timer);
+      } else if (async) {
+        delay(clone, function() { cycle(clone, options); });
+      } else {
+        cycle(clone);
+      }
+    }
+    else {
+      // fix TraceMonkey bug associated with clock fallbacks
+      // http://bugzil.la/509069
+      if (support.browser) {
+        runScript(uid + '=1;delete ' + uid);
+      }
+      // done
+      clone.emit('complete');
+    }
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Runs the benchmark.
+   *
+   * @memberOf Benchmark
+   * @param {Object} [options={}] Options object.
+   * @returns {Object} The benchmark instance.
+   * @example
+   *
+   * // basic usage
+   * bench.run();
+   *
+   * // or with options
+   * bench.run({ 'async': true });
+   */
+  function run(options) {
+    var me = this,
+        event = Event('start');
+
+    // set `running` to `false` so `reset()` won't call `abort()`
+    me.running = false;
+    me.reset();
+    me.running = true;
+
+    me.count = me.initCount;
+    me.times.timeStamp = +new Date;
+    me.emit(event);
+
+    if (!event.cancelled) {
+      options = { 'async': ((options = options && options.async) == null ? me.async : options) && support.timeout };
+
+      // for clones created within `compute()`
+      if (me._original) {
+        if (me.defer) {
+          Deferred(me);
+        } else {
+          cycle(me, options);
+        }
+      }
+      // for original benchmarks
+      else {
+        compute(me, options);
+      }
+    }
+    return me;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // Firefox 1 erroneously defines variable and argument names of functions on
+  // the function itself as non-configurable properties with `undefined` values.
+  // The bugginess continues as the `Benchmark` constructor has an argument
+  // named `options` and Firefox 1 will not assign a value to `Benchmark.options`,
+  // making it non-writable in the process, unless it is the first property
+  // assigned by for-in loop of `extend()`.
+  extend(Benchmark, {
+
+    /**
+     * The default options copied by benchmark instances.
+     *
+     * @static
+     * @memberOf Benchmark
+     * @type Object
+     */
+    'options': {
+
+      /**
+       * A flag to indicate that benchmark cycles will execute asynchronously
+       * by default.
+       *
+       * @memberOf Benchmark.options
+       * @type Boolean
+       */
+      'async': false,
+
+      /**
+       * A flag to indicate that the benchmark clock is deferred.
+       *
+       * @memberOf Benchmark.options
+       * @type Boolean
+       */
+      'defer': false,
+
+      /**
+       * The delay between test cycles (secs).
+       * @memberOf Benchmark.options
+       * @type Number
+       */
+      'delay': 0.005,
+
+      /**
+       * Displayed by Benchmark#toString when a `name` is not available
+       * (auto-generated if absent).
+       *
+       * @memberOf Benchmark.options
+       * @type String
+       */
+      'id': undefined,
+
+      /**
+       * The default number of times to execute a test on a benchmark's first cycle.
+       *
+       * @memberOf Benchmark.options
+       * @type Number
+       */
+      'initCount': 1,
+
+      /**
+       * The maximum time a benchmark is allowed to run before finishing (secs).
+       *
+       * Note: Cycle delays aren't counted toward the maximum time.
+       *
+       * @memberOf Benchmark.options
+       * @type Number
+       */
+      'maxTime': 5,
+
+      /**
+       * The minimum sample size required to perform statistical analysis.
+       *
+       * @memberOf Benchmark.options
+       * @type Number
+       */
+      'minSamples': 5,
+
+      /**
+       * The time needed to reduce the percent uncertainty of measurement to 1% (secs).
+       *
+       * @memberOf Benchmark.options
+       * @type Number
+       */
+      'minTime': 0,
+
+      /**
+       * The name of the benchmark.
+       *
+       * @memberOf Benchmark.options
+       * @type String
+       */
+      'name': undefined,
+
+      /**
+       * An event listener called when the benchmark is aborted.
+       *
+       * @memberOf Benchmark.options
+       * @type Function
+       */
+      'onAbort': undefined,
+
+      /**
+       * An event listener called when the benchmark completes running.
+       *
+       * @memberOf Benchmark.options
+       * @type Function
+       */
+      'onComplete': undefined,
+
+      /**
+       * An event listener called after each run cycle.
+       *
+       * @memberOf Benchmark.options
+       * @type Function
+       */
+      'onCycle': undefined,
+
+      /**
+       * An event listener called when a test errors.
+       *
+       * @memberOf Benchmark.options
+       * @type Function
+       */
+      'onError': undefined,
+
+      /**
+       * An event listener called when the benchmark is reset.
+       *
+       * @memberOf Benchmark.options
+       * @type Function
+       */
+      'onReset': undefined,
+
+      /**
+       * An event listener called when the benchmark starts running.
+       *
+       * @memberOf Benchmark.options
+       * @type Function
+       */
+      'onStart': undefined,
+
+      /**
+       * The reference time taken to execute the test once (usecs).
+       *
+       * @memberOf Benchmark.options
+       * @type Number
+       */
+      'reference': 0
+    },
+
+    /**
+     * Platform object with properties describing things like browser name,
+     * version, and operating system.
+     *
+     * @static
+     * @memberOf Benchmark
+     * @type Object
+     */
+    'platform': req('platform') || window.platform || {
+
+      /**
+       * The platform description.
+       *
+       * @memberOf Benchmark.platform
+       * @type String
+       */
+      'description': window.navigator && navigator.userAgent || null,
+
+      /**
+       * The name of the browser layout engine.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'layout': null,
+
+      /**
+       * The name of the product hosting the browser.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'product': null,
+
+      /**
+       * The name of the browser/environment.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'name': null,
+
+      /**
+       * The name of the product's manufacturer.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'manufacturer': null,
+
+      /**
+       * The name of the operating system.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'os': null,
+
+      /**
+       * The alpha/beta release indicator.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'prerelease': null,
+
+      /**
+       * The browser/environment version.
+       *
+       * @memberOf Benchmark.platform
+       * @type String|Null
+       */
+      'version': null,
+
+      /**
+       * Return platform description when the platform object is coerced to a string.
+       *
+       * @memberOf Benchmark.platform
+       * @type Function
+       * @returns {String} The platform description.
+       */
+      'toString': function() {
+        return this.description || '';
+      }
+    },
+
+    /**
+     * The semantic version number.
+     *
+     * @static
+     * @memberOf Benchmark
+     * @type String
+     */
+    'version': '1.0.0',
+
+    // an object of environment/feature detection flags
+    'support': support,
+
+    // clone objects
+    'deepClone': deepClone,
+
+    // iteration utility
+    'each': each,
+
+    // augment objects
+    'extend': extend,
+
+    // generic Array#filter
+    'filter': filter,
+
+    // generic Array#forEach
+    'forEach': forEach,
+
+    // generic own property iteration utility
+    'forOwn': forOwn,
+
+    // converts a number to a comma-separated string
+    'formatNumber': formatNumber,
+
+    // generic Object#hasOwnProperty
+    // (trigger hasKey's lazy define before assigning it to Benchmark)
+    'hasKey': (hasKey(Benchmark, ''), hasKey),
+
+    // generic Array#indexOf
+    'indexOf': indexOf,
+
+    // template utility
+    'interpolate': interpolate,
+
+    // invokes a method on each item in an array
+    'invoke': invoke,
+
+    // generic Array#join for arrays and objects
+    'join': join,
+
+    // generic Array#map
+    'map': map,
+
+    // retrieves a property value from each item in an array
+    'pluck': pluck,
+
+    // generic Array#reduce
+    'reduce': reduce
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  extend(Benchmark.prototype, {
+
+    /**
+     * The number of times a test was executed.
+     *
+     * @memberOf Benchmark
+     * @type Number
+     */
+    'count': 0,
+
+    /**
+     * The number of cycles performed while benchmarking.
+     *
+     * @memberOf Benchmark
+     * @type Number
+     */
+    'cycles': 0,
+
+    /**
+     * The number of executions per second.
+     *
+     * @memberOf Benchmark
+     * @type Number
+     */
+    'hz': 0,
+
+    /**
+     * The compiled test function.
+     *
+     * @memberOf Benchmark
+     * @type Function|String
+     */
+    'compiled': undefined,
+
+    /**
+     * The error object if the test failed.
+     *
+     * @memberOf Benchmark
+     * @type Object
+     */
+    'error': undefined,
+
+    /**
+     * The test to benchmark.
+     *
+     * @memberOf Benchmark
+     * @type Function|String
+     */
+    'fn': undefined,
+
+    /**
+     * A flag to indicate if the benchmark is aborted.
+     *
+     * @memberOf Benchmark
+     * @type Boolean
+     */
+    'aborted': false,
+
+    /**
+     * A flag to indicate if the benchmark is running.
+     *
+     * @memberOf Benchmark
+     * @type Boolean
+     */
+    'running': false,
+
+    /**
+     * Compiled into the test and executed immediately **before** the test loop.
+     *
+     * @memberOf Benchmark
+     * @type Function|String
+     * @example
+     *
+     * // basic usage
+     * var bench = Benchmark({
+     *   'setup': function() {
+     *     var c = this.count,
+     *         element = document.getElementById('container');
+     *     while (c--) {
+     *       element.appendChild(document.createElement('div'));
+     *     }
+     *   },
+     *   'fn': function() {
+     *     element.removeChild(element.lastChild);
+     *   }
+     * });
+     *
+     * // compiles to something like:
+     * var c = this.count,
+     *     element = document.getElementById('container');
+     * while (c--) {
+     *   element.appendChild(document.createElement('div'));
+     * }
+     * var start = new Date;
+     * while (count--) {
+     *   element.removeChild(element.lastChild);
+     * }
+     * var end = new Date - start;
+     *
+     * // or using strings
+     * var bench = Benchmark({
+     *   'setup': '\
+     *     var a = 0;\n\
+     *     (function() {\n\
+     *       (function() {\n\
+     *         (function() {',
+     *   'fn': 'a += 1;',
+     *   'teardown': '\
+     *          }())\n\
+     *        }())\n\
+     *      }())'
+     * });
+     *
+     * // compiles to something like:
+     * var a = 0;
+     * (function() {
+     *   (function() {
+     *     (function() {
+     *       var start = new Date;
+     *       while (count--) {
+     *         a += 1;
+     *       }
+     *       var end = new Date - start;
+     *     }())
+     *   }())
+     * }())
+     */
+    'setup': noop,
+
+    /**
+     * Compiled into the test and executed immediately **after** the test loop.
+     *
+     * @memberOf Benchmark
+     * @type Function|String
+     */
+    'teardown': noop,
+
+    /**
+     * An object of stats including mean, margin or error, and standard deviation.
+     *
+     * @memberOf Benchmark
+     * @type Object
+     */
+    'stats': {
+
+      /**
+       * The margin of error.
+       *
+       * @memberOf Benchmark#stats
+       * @type Number
+       */
+      'moe': 0,
+
+      /**
+       * The relative margin of error (expressed as a percentage of the mean).
+       *
+       * @memberOf Benchmark#stats
+       * @type Number
+       */
+      'rme': 0,
+
+      /**
+       * The standard error of the mean.
+       *
+       * @memberOf Benchmark#stats
+       * @type Number
+       */
+      'sem': 0,
+
+      /**
+       * The sample standard deviation.
+       *
+       * @memberOf Benchmark#stats
+       * @type Number
+       */
+      'deviation': 0,
+
+      /**
+       * The sample arithmetic mean.
+       *
+       * @memberOf Benchmark#stats
+       * @type Number
+       */
+      'mean': 0,
+
+      /**
+       * The array of sampled periods.
+       *
+       * @memberOf Benchmark#stats
+       * @type Array
+       */
+      'sample': [],
+
+      /**
+       * The sample variance.
+       *
+       * @memberOf Benchmark#stats
+       * @type Number
+       */
+      'variance': 0
+    },
+
+    /**
+     * An object of timing data including cycle, elapsed, period, start, and stop.
+     *
+     * @memberOf Benchmark
+     * @type Object
+     */
+    'times': {
+
+      /**
+       * The time taken to complete the last cycle (secs).
+       *
+       * @memberOf Benchmark#times
+       * @type Number
+       */
+      'cycle': 0,
+
+      /**
+       * The time taken to complete the benchmark (secs).
+       *
+       * @memberOf Benchmark#times
+       * @type Number
+       */
+      'elapsed': 0,
+
+      /**
+       * The time taken to execute the test once (secs).
+       *
+       * @memberOf Benchmark#times
+       * @type Number
+       */
+      'period': 0,
+
+      /**
+       * A timestamp of when the benchmark started (ms).
+       *
+       * @memberOf Benchmark#times
+       * @type Number
+       */
+      'timeStamp': 0
+    },
+
+    // aborts benchmark (does not record times)
+    'abort': abort,
+
+    // creates a new benchmark using the same test and options
+    'clone': clone,
+
+    // compares benchmark's hertz with another
+    'compare': compare,
+
+    // executes listeners
+    'emit': emit,
+
+    // get listeners
+    'listeners': listeners,
+
+    // unregister listeners
+    'off': off,
+
+    // register listeners
+    'on': on,
+
+    // reset benchmark properties
+    'reset': reset,
+
+    // runs the benchmark
+    'run': run,
+
+    // pretty print benchmark info
+    'toString': toStringBench
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  extend(Deferred.prototype, {
+
+    /**
+     * The deferred benchmark instance.
+     *
+     * @memberOf Benchmark.Deferred
+     * @type Object
+     */
+    'benchmark': null,
+
+    /**
+     * The number of deferred cycles performed while benchmarking.
+     *
+     * @memberOf Benchmark.Deferred
+     * @type Number
+     */
+    'cycles': 0,
+
+    /**
+     * The time taken to complete the deferred benchmark (secs).
+     *
+     * @memberOf Benchmark.Deferred
+     * @type Number
+     */
+    'elapsed': 0,
+
+    /**
+     * A timestamp of when the deferred benchmark started (ms).
+     *
+     * @memberOf Benchmark.Deferred
+     * @type Number
+     */
+    'timeStamp': 0,
+
+    // cycles/completes the deferred benchmark
+    'resolve': resolve
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  extend(Event.prototype, {
+
+    /**
+     * A flag to indicate if the emitters listener iteration is aborted.
+     *
+     * @memberOf Benchmark.Event
+     * @type Boolean
+     */
+    'aborted': false,
+
+    /**
+     * A flag to indicate if the default action is cancelled.
+     *
+     * @memberOf Benchmark.Event
+     * @type Boolean
+     */
+    'cancelled': false,
+
+    /**
+     * The object whose listeners are currently being processed.
+     *
+     * @memberOf Benchmark.Event
+     * @type Object
+     */
+    'currentTarget': undefined,
+
+    /**
+     * The return value of the last executed listener.
+     *
+     * @memberOf Benchmark.Event
+     * @type Mixed
+     */
+    'result': undefined,
+
+    /**
+     * The object to which the event was originally emitted.
+     *
+     * @memberOf Benchmark.Event
+     * @type Object
+     */
+    'target': undefined,
+
+    /**
+     * A timestamp of when the event was created (ms).
+     *
+     * @memberOf Benchmark.Event
+     * @type Number
+     */
+    'timeStamp': 0,
+
+    /**
+     * The event type.
+     *
+     * @memberOf Benchmark.Event
+     * @type String
+     */
+    'type': ''
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The default options copied by suite instances.
+   *
+   * @static
+   * @memberOf Benchmark.Suite
+   * @type Object
+   */
+  Suite.options = {
+
+    /**
+     * The name of the suite.
+     *
+     * @memberOf Benchmark.Suite.options
+     * @type String
+     */
+    'name': undefined
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  extend(Suite.prototype, {
+
+    /**
+     * The number of benchmarks in the suite.
+     *
+     * @memberOf Benchmark.Suite
+     * @type Number
+     */
+    'length': 0,
+
+    /**
+     * A score computed using the normalized result of each benchmark in the suite.
+     *
+     * @memberOf Benchmark.Suite
+     * @type Number
+     */
+    'score': 0,
+
+    /**
+     * A flag to indicate if the suite is aborted.
+     *
+     * @memberOf Benchmark.Suite
+     * @type Boolean
+     */
+    'aborted': false,
+
+    /**
+     * A flag to indicate if the suite is running.
+     *
+     * @memberOf Benchmark.Suite
+     * @type Boolean
+     */
+    'running': false,
+
+    /**
+     * An `Array#forEach` like method.
+     * Callbacks may terminate the loop by explicitly returning `false`.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {Function} callback The function called per iteration.
+     * @returns {Object} The suite iterated over.
+     */
+    'forEach': methodize(forEach),
+
+    /**
+     * An `Array#indexOf` like method.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {Mixed} value The value to search for.
+     * @returns {Number} The index of the matched value or `-1`.
+     */
+    'indexOf': methodize(indexOf),
+
+    /**
+     * Invokes a method on all benchmarks in the suite.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {String|Object} name The name of the method to invoke OR options object.
+     * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+     * @returns {Array} A new array of values returned from each method invoked.
+     */
+    'invoke': methodize(invoke),
+
+    /**
+     * Converts the suite of benchmarks to a string.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {String} [separator=','] A string to separate each element of the array.
+     * @returns {String} The string.
+     */
+    'join': [].join,
+
+    /**
+     * An `Array#map` like method.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {Function} callback The function called per iteration.
+     * @returns {Array} A new array of values returned by the callback.
+     */
+    'map': methodize(map),
+
+    /**
+     * Retrieves the value of a specified property from all benchmarks in the suite.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {String} property The property to pluck.
+     * @returns {Array} A new array of property values.
+     */
+    'pluck': methodize(pluck),
+
+    /**
+     * Removes the last benchmark from the suite and returns it.
+     *
+     * @memberOf Benchmark.Suite
+     * @returns {Mixed} The removed benchmark.
+     */
+    'pop': [].pop,
+
+    /**
+     * Appends benchmarks to the suite.
+     *
+     * @memberOf Benchmark.Suite
+     * @returns {Number} The suite's new length.
+     */
+    'push': [].push,
+
+    /**
+     * Sorts the benchmarks of the suite.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {Function} [compareFn=null] A function that defines the sort order.
+     * @returns {Object} The sorted suite.
+     */
+    'sort': [].sort,
+
+    /**
+     * An `Array#reduce` like method.
+     *
+     * @memberOf Benchmark.Suite
+     * @param {Function} callback The function called per iteration.
+     * @param {Mixed} accumulator Initial value of the accumulator.
+     * @returns {Mixed} The accumulator.
+     */
+    'reduce': methodize(reduce),
+
+    // aborts all benchmarks in the suite
+    'abort': abortSuite,
+
+    // adds a benchmark to the suite
+    'add': add,
+
+    // creates a new suite with cloned benchmarks
+    'clone': cloneSuite,
+
+    // executes listeners of a specified type
+    'emit': emit,
+
+    // creates a new suite of filtered benchmarks
+    'filter': filterSuite,
+
+    // get listeners
+    'listeners': listeners,
+
+    // unregister listeners
+    'off': off,
+
+   // register listeners
+    'on': on,
+
+    // resets all benchmarks in the suite
+    'reset': resetSuite,
+
+    // runs all benchmarks in the suite
+    'run': runSuite,
+
+    // array methods
+    'concat': concat,
+
+    'reverse': reverse,
+
+    'shift': shift,
+
+    'slice': slice,
+
+    'splice': splice,
+
+    'unshift': unshift
+  });
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Deferred, Event and Suite
+  extend(Benchmark, {
+    'Deferred': Deferred,
+    'Event': Event,
+    'Suite': Suite
+  });
+
+  // expose Benchmark
+  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // define as an anonymous module so, through path mapping, it can be aliased
+    define(function() {
+      return Benchmark;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports) {
+    // in Node.js or RingoJS v0.8.0+
+    if (typeof module == 'object' && module && module.exports == freeExports) {
+      (module.exports = Benchmark).Benchmark = Benchmark;
+    }
+    // in Narwhal or RingoJS v0.7.0-
+    else {
+      freeExports.Benchmark = Benchmark;
+    }
+  }
+  // in a browser or Rhino
+  else {
+    // use square bracket notation so Closure Compiler won't munge `Benchmark`
+    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
+    window['Benchmark'] = Benchmark;
+  }
+
+  // trigger clock's lazy define early to avoid a security error
+  if (support.air) {
+    clock({ '_original': { 'fn': noop, 'count': 1, 'options': {} } });
+  }
+}(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/LICENSE.txt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/LICENSE.txt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/LICENSE.txt	(revision 533)
@@ -0,0 +1,20 @@
+Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/README.md	(revision 533)
@@ -0,0 +1,98 @@
+# Platform.js <sup>v1.0.0</sup>
+
+A platform detection library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>.
+
+## Disclaimer
+
+Platform.js is for informational purposes only and **not** intended as a substitution for [feature detection/inference](http://allyoucanleet.com/post/18087210413/feature-testing-costs#screencast2) checks.
+
+## BestieJS
+
+Platform.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
+
+## Documentation
+
+The documentation for Platform.js can be viewed here: [/doc/README.md](https://github.com/bestiejs/platform.js/blob/master/doc/README.md#readme)
+
+For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/platform.js/wiki/Roadmap).
+
+## Support
+
+Platform.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-14, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
+
+## Installation and usage
+
+In a browser or Adobe AIR:
+
+```html
+<script src="platform.js"></script>
+```
+
+Via [npm](http://npmjs.org/):
+
+```bash
+npm install platform
+```
+
+In [Node.js](http://nodejs.org/) and [RingoJS](http://ringojs.org/):
+
+```js
+var platform = require('platform');
+```
+
+In [Rhino](http://www.mozilla.org/rhino/):
+
+```js
+load('platform.js');
+```
+
+In an AMD loader like [RequireJS](http://requirejs.org/):
+
+```js
+require({
+  'paths': {
+    'platform': 'path/to/platform'
+  }
+},
+['platform'], function(platform) {
+  console.log(platform.name);
+});
+```
+
+Usage example:
+
+```js
+// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition
+platform.name; // 'IE'
+platform.version; // '10.0'
+platform.layout; // 'Trident'
+platform.os; // 'Windows Server 2008 R2 / 7 x64'
+platform.description; // 'IE 10.0 x86 (platform preview; running in IE 7 mode) on Windows Server 2008 R2 / 7 x64'
+
+// or on an iPad
+platform.name; // 'Safari'
+platform.version; // '5.1'
+platform.product; // 'iPad'
+platform.manufacturer; // 'Apple'
+platform.layout; // 'WebKit'
+platform.os; // 'iOS 5.0'
+platform.description; // 'Safari 5.1 on Apple iPad (iOS 5.0)'
+
+// or parsing a given UA string
+var info = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7.2; en; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 11.52');
+info.name; // 'Opera'
+info.version; // '11.52'
+info.layout; // 'Presto'
+info.os; // 'Mac OS X 10.7.2'
+info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2'
+```
+
+## Author
+
+* [John-David Dalton](http://allyoucanleet.com/)
+  [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
+
+## Contributors
+
+* [Mathias Bynens](http://mathiasbynens.be/)
+  [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/platform.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/platform.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/platform.js	(revision 533)
@@ -0,0 +1,996 @@
+/*!
+ * Platform.js v1.0.0 <http://mths.be/platform>
+ * Copyright 2010-2013 John-David Dalton <http://allyoucanleet.com/>
+ * Available under MIT license <http://mths.be/mit>
+ */
+;(function(window) {
+  'use strict';
+
+  /** Backup possible window/global object */
+  var oldWin = window;
+
+  /** Detect free variable `exports` */
+  var freeExports = typeof exports == 'object' && exports;
+
+  /** Detect free variable `global` */
+  var freeGlobal = typeof global == 'object' && global &&
+    (global == global.global ? (window = global) : global);
+
+  /** Opera regexp */
+  var reOpera = /Opera/;
+
+  /** Used to resolve a value's internal [[Class]] */
+  var toString = {}.toString;
+
+  /** Detect Java environment */
+  var java = /Java/.test(getClassOf(window.java)) && window.java;
+
+  /** A character to represent alpha */
+  var alpha = java ? 'a' : '\u03b1';
+
+  /** A character to represent beta */
+  var beta = java ? 'b' : '\u03b2';
+
+  /** Browser document object */
+  var doc = window.document || {};
+
+  /** Used to check for own properties of an object */
+  var hasOwnProperty = {}.hasOwnProperty;
+
+  /** Browser navigator object */
+  var nav = window.navigator || {};
+
+  /**
+   * Detect Opera browser
+   * http://www.howtocreate.co.uk/operaStuff/operaObject.html
+   * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
+   */
+  var opera = window.operamini || window.opera;
+
+  /** Opera [[Class]] */
+  var operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null);
+
+  /** Possible global object */
+  var thisBinding = this;
+
+  /** Browser user agent string */
+  var userAgent = nav.userAgent || '';
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Capitalizes a string value.
+   *
+   * @private
+   * @param {String} string The string to capitalize.
+   * @returns {String} The capitalized string.
+   */
+  function capitalize(string) {
+    string = String(string);
+    return string.charAt(0).toUpperCase() + string.slice(1);
+  }
+
+  /**
+   * An iteration utility for arrays and objects.
+   *
+   * @private
+   * @param {Array|Object} object The object to iterate over.
+   * @param {Function} callback The function called per iteration.
+   */
+  function each(object, callback) {
+    var index = -1,
+        length = object.length;
+
+    if (length == length >>> 0) {
+      while (++index < length) {
+        callback(object[index], index, object);
+      }
+    } else {
+      forOwn(object, callback);
+    }
+  }
+
+  /**
+   * Trim and conditionally capitalize string values.
+   *
+   * @private
+   * @param {String} string The string to format.
+   * @returns {String} The formatted string.
+   */
+  function format(string) {
+    string = trim(string);
+    return /^(?:webOS|i(?:OS|P))/.test(string)
+      ? string
+      : capitalize(string);
+  }
+
+  /**
+   * Iterates over an object's own properties, executing the `callback` for each.
+   *
+   * @private
+   * @param {Object} object The object to iterate over.
+   * @param {Function} callback The function executed per own property.
+   */
+  function forOwn(object, callback) {
+    for (var key in object) {
+      hasKey(object, key) && callback(object[key], key, object);
+    }
+  }
+
+  /**
+   * Gets the internal [[Class]] of a value.
+   *
+   * @private
+   * @param {Mixed} value The value.
+   * @returns {String} The [[Class]].
+   */
+  function getClassOf(value) {
+    return value == null
+      ? capitalize(value)
+      : toString.call(value).slice(8, -1);
+  }
+
+  /**
+   * Checks if an object has the specified key as a direct property.
+   *
+   * @private
+   * @param {Object} object The object to check.
+   * @param {String} key The key to check for.
+   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+   */
+  function hasKey() {
+    // lazy define for others (not as accurate)
+    hasKey = function(object, key) {
+      var parent = object != null && (object.constructor || Object).prototype;
+      return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);
+    };
+    // for modern browsers
+    if (getClassOf(hasOwnProperty) == 'Function') {
+      hasKey = function(object, key) {
+        return object != null && hasOwnProperty.call(object, key);
+      };
+    }
+    // for Safari 2
+    else if ({}.__proto__ == Object.prototype) {
+      hasKey = function(object, key) {
+        var result = false;
+        if (object != null) {
+          object = Object(object);
+          object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];
+        }
+        return result;
+      };
+    }
+    return hasKey.apply(this, arguments);
+  }
+
+  /**
+   * Host objects can return type values that are different from their actual
+   * data type. The objects we are concerned with usually return non-primitive
+   * types of object, function, or unknown.
+   *
+   * @private
+   * @param {Mixed} object The owner of the property.
+   * @param {String} property The property to check.
+   * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
+   */
+  function isHostType(object, property) {
+    var type = object != null ? typeof object[property] : 'number';
+    return !/^(?:boolean|number|string|undefined)$/.test(type) &&
+      (type == 'object' ? !!object[property] : true);
+  }
+
+  /**
+   * Prepares a string for use in a RegExp constructor by making hyphens and
+   * spaces optional.
+   *
+   * @private
+   * @param {String} string The string to qualify.
+   * @returns {String} The qualified string.
+   */
+  function qualify(string) {
+    return String(string).replace(/([ -])(?!$)/g, '$1?');
+  }
+
+  /**
+   * A bare-bones` Array#reduce` like utility function.
+   *
+   * @private
+   * @param {Array} array The array to iterate over.
+   * @param {Function} callback The function called per iteration.
+   * @param {Mixed} accumulator Initial value of the accumulator.
+   * @returns {Mixed} The accumulator.
+   */
+  function reduce(array, callback) {
+    var accumulator = null;
+    each(array, function(value, index) {
+      accumulator = callback(accumulator, value, index, array);
+    });
+    return accumulator;
+  }
+
+  /**
+   * Removes leading and trailing whitespace from a string.
+   *
+   * @private
+   * @param {String} string The string to trim.
+   * @returns {String} The trimmed string.
+   */
+  function trim(string) {
+    return String(string).replace(/^ +| +$/g, '');
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a new platform object.
+   *
+   * @memberOf platform
+   * @param {String} [ua = navigator.userAgent] The user agent string.
+   * @returns {Object} A platform object.
+   */
+  function parse(ua) {
+
+    ua || (ua = userAgent);
+
+    /** Temporary variable used over the script's lifetime */
+    var data;
+
+    /** The CPU architecture */
+    var arch = ua;
+
+    /** Platform description array */
+    var description = [];
+
+    /** Platform alpha/beta indicator */
+    var prerelease = null;
+
+    /** A flag to indicate that environment features should be used to resolve the platform */
+    var useFeatures = ua == userAgent;
+
+    /** The browser/environment version */
+    var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
+
+    /* Detectable layout engines (order is important) */
+    var layout = getLayout([
+      { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
+      'iCab',
+      'Presto',
+      'NetFront',
+      'Tasman',
+      'Trident',
+      'KHTML',
+      'Gecko'
+    ]);
+
+    /* Detectable browser names (order is important) */
+    var name = getName([
+      'Adobe AIR',
+      'Arora',
+      'Avant Browser',
+      'Camino',
+      'Epiphany',
+      'Fennec',
+      'Flock',
+      'Galeon',
+      'GreenBrowser',
+      'iCab',
+      'Iceweasel',
+      'Iron',
+      'K-Meleon',
+      'Konqueror',
+      'Lunascape',
+      'Maxthon',
+      'Midori',
+      'Nook Browser',
+      'PhantomJS',
+      'Raven',
+      'Rekonq',
+      'RockMelt',
+      'SeaMonkey',
+      { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+      'Sleipnir',
+      'SlimBrowser',
+      'Sunrise',
+      'Swiftfox',
+      'WebPositive',
+      'Opera Mini',
+      'Opera',
+      'Chrome',
+      { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
+      { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
+      { 'label': 'IE', 'pattern': 'MSIE' },
+      'Safari'
+    ]);
+
+    /* Detectable products (order is important) */
+    var product = getProduct([
+      'BlackBerry',
+      { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
+      { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
+      'Google TV',
+      'iPad',
+      'iPod',
+      'iPhone',
+      'Kindle',
+      { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
+      'Nook',
+      'PlayBook',
+      'PlayStation Vita',
+      'TouchPad',
+      'Transformer',
+      'Xoom'
+    ]);
+
+    /* Detectable manufacturers */
+    var manufacturer = getManufacturer({
+      'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
+      'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
+      'Asus': { 'Transformer': 1 },
+      'Barnes & Noble': { 'Nook': 1 },
+      'BlackBerry': { 'PlayBook': 1 },
+      'Google': { 'Google TV': 1 },
+      'HP': { 'TouchPad': 1 },
+      'LG': { },
+      'Motorola': { 'Xoom': 1 },
+      'Nokia': { },
+      'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1 },
+      'Sony': { 'PlayStation Vita': 1 }
+    });
+
+    /* Detectable OSes (order is important) */
+    var os = getOS([
+      'Android',
+      'CentOS',
+      'Debian',
+      'Fedora',
+      'FreeBSD',
+      'Gentoo',
+      'Haiku',
+      'Kubuntu',
+      'Linux Mint',
+      'Red Hat',
+      'SuSE',
+      'Ubuntu',
+      'Xubuntu',
+      'Cygwin',
+      'Symbian OS',
+      'hpwOS',
+      'webOS ',
+      'webOS',
+      'Tablet OS',
+      'Linux',
+      'Mac OS X',
+      'Macintosh',
+      'Mac',
+      'Windows 98;',
+      'Windows '
+    ]);
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Picks the layout engine from an array of guesses.
+     *
+     * @private
+     * @param {Array} guesses An array of guesses.
+     * @returns {String|Null} The detected layout engine.
+     */
+    function getLayout(guesses) {
+      return reduce(guesses, function(result, guess) {
+        return result || RegExp('\\b' + (
+          guess.pattern || qualify(guess)
+        ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+      });
+    }
+
+    /**
+     * Picks the manufacturer from an array of guesses.
+     *
+     * @private
+     * @param {Array} guesses An array of guesses.
+     * @returns {String|Null} The detected manufacturer.
+     */
+    function getManufacturer(guesses) {
+      return reduce(guesses, function(result, value, key) {
+        // lookup the manufacturer by product or scan the UA for the manufacturer
+        return result || (
+          value[product] ||
+          value[0/*Opera 9.25 fix*/, /^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
+          RegExp('\\b' + (key.pattern || qualify(key)) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
+        ) && (key.label || key);
+      });
+    }
+
+    /**
+     * Picks the browser name from an array of guesses.
+     *
+     * @private
+     * @param {Array} guesses An array of guesses.
+     * @returns {String|Null} The detected browser name.
+     */
+    function getName(guesses) {
+      return reduce(guesses, function(result, guess) {
+        return result || RegExp('\\b' + (
+          guess.pattern || qualify(guess)
+        ) + '\\b', 'i').exec(ua) && (guess.label || guess);
+      });
+    }
+
+    /**
+     * Picks the OS name from an array of guesses.
+     *
+     * @private
+     * @param {Array} guesses An array of guesses.
+     * @returns {String|Null} The detected OS name.
+     */
+    function getOS(guesses) {
+      return reduce(guesses, function(result, guess) {
+        var pattern = guess.pattern || qualify(guess);
+        if (!result && (result =
+            RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua))) {
+          // platform tokens defined at
+          // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+          // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
+          data = {
+            '6.2':  '8',
+            '6.1':  'Server 2008 R2 / 7',
+            '6.0':  'Server 2008 / Vista',
+            '5.2':  'Server 2003 / XP 64-bit',
+            '5.1':  'XP',
+            '5.01': '2000 SP1',
+            '5.0':  '2000',
+            '4.0':  'NT',
+            '4.90': 'ME'
+          };
+          // detect Windows version from platform tokens
+          if (/^Win/i.test(result) &&
+              (data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) {
+            result = 'Windows ' + data;
+          }
+          // correct character case and cleanup
+          result = format(String(result)
+            .replace(RegExp(pattern, 'i'), guess.label || guess)
+            .replace(/ ce$/i, ' CE')
+            .replace(/hpw/i, 'web')
+            .replace(/Macintosh/, 'Mac OS')
+            .replace(/_PowerPC/i, ' OS')
+            .replace(/(OS X) [^ \d]+/i, '$1')
+            .replace(/\/(\d)/, ' $1')
+            .replace(/_/g, '.')
+            .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
+            .replace(/x86\.64/gi, 'x86_64')
+            .split(' on ')[0]);
+        }
+        return result;
+      });
+    }
+
+    /**
+     * Picks the product name from an array of guesses.
+     *
+     * @private
+     * @param {Array} guesses An array of guesses.
+     * @returns {String|Null} The detected product name.
+     */
+    function getProduct(guesses) {
+      return reduce(guesses, function(result, guess) {
+        var pattern = guess.pattern || qualify(guess);
+        if (!result && (result =
+              RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
+              RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
+            )) {
+          // split by forward slash and append product version if needed
+          if ((result = String(guess.label || result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
+            result[0] += ' ' + result[1];
+          }
+          // correct character case and cleanup
+          guess = guess.label || guess;
+          result = format(result[0]
+            .replace(RegExp(pattern, 'i'), guess)
+            .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
+            .replace(RegExp('(' + guess + ')(\\w)', 'i'), '$1 $2'));
+        }
+        return result;
+      });
+    }
+
+    /**
+     * Resolves the version using an array of UA patterns.
+     *
+     * @private
+     * @param {Array} patterns An array of UA patterns.
+     * @returns {String|Null} The detected version.
+     */
+    function getVersion(patterns) {
+      return reduce(patterns, function(result, pattern) {
+        return result || (RegExp(pattern +
+          '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
+      });
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Returns `platform.description` when the platform object is coerced to a string.
+     *
+     * @name toString
+     * @memberOf platform
+     * @returns {String} Returns `platform.description` if available, else an empty string.
+     */
+    function toStringPlatform() {
+      return this.description || '';
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    // convert layout to an array so we can add extra details
+    layout && (layout = [layout]);
+
+    // detect product names that contain their manufacturer's name
+    if (manufacturer && !product) {
+      product = getProduct([manufacturer]);
+    }
+    // clean up Google TV
+    if ((data = /Google TV/.exec(product))) {
+      product = data[0];
+    }
+    // detect simulators
+    if (/\bSimulator\b/i.test(ua)) {
+      product = (product ? product + ' ' : '') + 'Simulator';
+    }
+    // detect iOS
+    if (/^iP/.test(product)) {
+      name || (name = 'Safari');
+      os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
+        ? ' ' + data[1].replace(/_/g, '.')
+        : '');
+    }
+    // detect Kubuntu
+    else if (name == 'Konqueror' && !/buntu/i.test(os)) {
+      os = 'Kubuntu';
+    }
+    // detect Android browsers
+    else if (manufacturer && manufacturer != 'Google' &&
+        /Chrome|Vita/.test(name + ';' + product)) {
+      name = 'Android Browser';
+      os = /Android/.test(os) ? os : 'Android';
+    }
+    // detect false positives for Firefox/Safari
+    else if (!name || (data = !/\bMinefield\b/i.test(ua) && /Firefox|Safari/.exec(name))) {
+      // escape the `/` for Firefox 1
+      if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
+        // clear name of false positives
+        name = null;
+      }
+      // reassign a generic name
+      if ((data = product || manufacturer || os) &&
+          (product || manufacturer || /Android|Symbian OS|Tablet OS|webOS/.test(os))) {
+        name = /[a-z]+(?: Hat)?/i.exec(/Android/.test(os) ? os : data) + ' Browser';
+      }
+    }
+    // detect non-Opera versions (order is important)
+    if (!version) {
+      version = getVersion([
+        '(?:Cloud9|CriOS|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))',
+        'Version',
+        qualify(name),
+        '(?:Firefox|Minefield|NetFront)'
+      ]);
+    }
+    // detect stubborn layout engines
+    if (layout == 'iCab' && parseFloat(version) > 3) {
+      layout = ['WebKit'];
+    } else if (data =
+        /Opera/.test(name) && 'Presto' ||
+        /\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' ||
+        !layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) {
+      layout = [data];
+    }
+    // leverage environment features
+    if (useFeatures) {
+      // detect server-side environments
+      // Rhino has a global function while others have a global object
+      if (isHostType(window, 'global')) {
+        if (java) {
+          data = java.lang.System;
+          arch = data.getProperty('os.arch');
+          os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
+        }
+        if (typeof exports == 'object' && exports) {
+          // if `thisBinding` is the [ModuleScope]
+          if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {
+            os || (os = data[0].os || null);
+            try {
+              data[1] = require('ringo/engine').version;
+              version = data[1].join('.');
+              name = 'RingoJS';
+            } catch(e) {
+              if (data[0].global == freeGlobal) {
+                name = 'Narwhal';
+              }
+            }
+          } else if (typeof process == 'object' && (data = process)) {
+            name = 'Node.js';
+            arch = data.arch;
+            os = data.platform;
+            version = /[\d.]+/.exec(data.version)[0];
+          }
+        } else if (getClassOf(window.environment) == 'Environment') {
+          name = 'Rhino';
+        }
+      }
+      // detect Adobe AIR
+      else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') {
+        name = 'Adobe AIR';
+        os = data.flash.system.Capabilities.os;
+      }
+      // detect PhantomJS
+      else if (getClassOf(data = window.phantom) == 'RuntimeObject') {
+        name = 'PhantomJS';
+        version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
+      }
+      // detect IE compatibility modes
+      else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
+        // we're in compatibility mode when the Trident version + 4 doesn't
+        // equal the document mode
+        version = [version, doc.documentMode];
+        if ((data = +data[1] + 4) != version[1]) {
+          description.push('IE ' + version[1] + ' mode');
+          layout[1] = '';
+          version[1] = data;
+        }
+        version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
+      }
+      os = os && format(os);
+    }
+    // detect prerelease phases
+    if (version && (data =
+        /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
+        /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
+        /\bMinefield\b/i.test(ua) && 'a')) {
+      prerelease = /b/i.test(data) ? 'beta' : 'alpha';
+      version = version.replace(RegExp(data + '\\+?$'), '') +
+        (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
+    }
+    // rename code name "Fennec"
+    if (name == 'Fennec') {
+      name = 'Firefox Mobile';
+    }
+    // obscure Maxthon's unreliable version
+    else if (name == 'Maxthon' && version) {
+      version = version.replace(/\.[\d.]+/, '.x');
+    }
+    // detect Silk desktop/accelerated modes
+    else if (name == 'Silk') {
+      if (!/Mobi/i.test(ua)) {
+        os = 'Android';
+        description.unshift('desktop mode');
+      }
+      if (/Accelerated *= *true/i.test(ua)) {
+        description.unshift('accelerated');
+      }
+    }
+    // detect Windows Phone desktop mode
+    else if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
+      name += ' Mobile';
+      os = 'Windows Phone OS ' + data + '.x';
+      description.unshift('desktop mode');
+    }
+    // add mobile postfix
+    else if ((name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) &&
+        (os == 'Windows CE' || /Mobi/i.test(ua))) {
+      name += ' Mobile';
+    }
+    // detect IE platform preview
+    else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) {
+      description.unshift('platform preview');
+    }
+    // detect BlackBerry OS version
+    // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
+    else if (/BlackBerry/.test(product) && (data =
+        (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
+        version)) {
+      os = 'Device Software ' + data;
+      version = null;
+    }
+    // detect Opera identifying/masking itself as another browser
+    // http://www.opera.com/support/kb/view/843/
+    else if (this != forOwn && (
+          (useFeatures && opera) ||
+          (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
+          (name == 'Firefox' && /OS X (?:\d+\.){2,}/.test(os)) ||
+          (name == 'IE' && (
+            (os && !/^Win/.test(os) && version > 5.5) ||
+            /Windows XP/.test(os) && version > 8 ||
+            version == 8 && !/Trident/.test(ua)
+          ))
+        ) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {
+
+      // when "indentifying", the UA contains both Opera and the other browser's name
+      data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
+      if (reOpera.test(name)) {
+        if (/IE/.test(data) && os == 'Mac OS') {
+          os = null;
+        }
+        data = 'identify' + data;
+      }
+      // when "masking", the UA contains only the other browser's name
+      else {
+        data = 'mask' + data;
+        if (operaClass) {
+          name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
+        } else {
+          name = 'Opera';
+        }
+        if (/IE/.test(data)) {
+          os = null;
+        }
+        if (!useFeatures) {
+          version = null;
+        }
+      }
+      layout = ['Presto'];
+      description.push(data);
+    }
+    // detect WebKit Nightly and approximate Chrome/Safari versions
+    if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
+      // correct build for numeric comparison
+      // (e.g. "532.5" becomes "532.05")
+      data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
+      // nightly builds are postfixed with a `+`
+      if (name == 'Safari' && data[1].slice(-1) == '+') {
+        name = 'WebKit Nightly';
+        prerelease = 'alpha';
+        version = data[1].slice(0, -1);
+      }
+      // clear incorrect browser versions
+      else if (version == data[1] ||
+          version == (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1]) {
+        version = null;
+      }
+      // use the full Chrome version when available
+      data = [data[0], (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]];
+
+      // detect JavaScriptCore
+      // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
+      if (!useFeatures || (/internal|\n/i.test(toString.toString()) && !data[1])) {
+        layout[1] = 'like Safari';
+        data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');
+      } else {
+        layout[1] = 'like Chrome';
+        data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : '21');
+      }
+      // add the postfix of ".x" or "+" for approximate versions
+      layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');
+      // obscure version for some Safari 1-2 releases
+      if (name == 'Safari' && (!version || parseInt(version) > 45)) {
+        version = data;
+      }
+    }
+    // detect Opera desktop modes
+    if (name == 'Opera' &&  (data = /(?:zbov|zvav)$/.exec(os))) {
+      name += ' ';
+      description.unshift('desktop mode');
+      if (data == 'zvav') {
+        name += 'Mini';
+        version = null;
+      } else {
+        name += 'Mobile';
+      }
+    }
+    // detect Chrome desktop mode
+    else if (name == 'Safari' && /Chrome/.exec(layout[1])) {
+      description.unshift('desktop mode');
+      name = 'Chrome Mobile';
+      version = null;
+
+      if (/Mac OS X/.test(os)) {
+        manufacturer = 'Apple';
+        os = 'iOS 4.3+';
+      } else {
+        os = null;
+      }
+    }
+    // strip incorrect OS versions
+    if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 &&
+        ua.indexOf('/' + data + '-') > -1) {
+      os = trim(os.replace(data, ''));
+    }
+    // add layout engine
+    if (layout && !/Avant|Nook/.test(name) && (
+        /Browser|Lunascape|Maxthon/.test(name) ||
+        /^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) {
+      // don't add layout details to description if they are falsey
+      (data = layout[layout.length - 1]) && description.push(data);
+    }
+    // combine contextual information
+    if (description.length) {
+      description = ['(' + description.join('; ') + ')'];
+    }
+    // append manufacturer
+    if (manufacturer && product && product.indexOf(manufacturer) < 0) {
+      description.push('on ' + manufacturer);
+    }
+    // append product
+    if (product) {
+      description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);
+    }
+    // parse OS into an object
+    if (os) {
+      data = / ([\d.+]+)$/.exec(os);
+      os = {
+        'architecture': 32,
+        'family': data ? os.replace(data[0], '') : os,
+        'version': data ? data[1] : null,
+        'toString': function() {
+          var version = this.version;
+          return this.family + (version ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
+        }
+      };
+    }
+    // add browser/OS architecture
+    if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
+      if (os) {
+        os.architecture = 64;
+        os.family = os.family.replace(RegExp(' *' + data), '');
+      }
+      if (name && (/WOW64/i.test(ua) ||
+          (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
+        description.unshift('32-bit');
+      }
+    }
+
+    ua || (ua = null);
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * The platform object.
+     *
+     * @name platform
+     * @type Object
+     */
+    return {
+
+      /**
+       * The browser/environment version.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'version': name && version && (description.unshift(version), version),
+
+      /**
+       * The name of the browser/environment.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'name': name && (description.unshift(name), name),
+
+      /**
+       * The name of the operating system.
+       *
+       * @memberOf platform
+       * @type Object
+       */
+      'os': os
+        ? (name &&
+            !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product)) &&
+              description.push(product ? '(' + os + ')' : 'on ' + os), os)
+        : {
+
+          /**
+           * The CPU architecture the OS is built for.
+           *
+           * @memberOf platform.os
+           * @type Number|Null
+           */
+          'architecture': null,
+
+          /**
+           * The family of the OS.
+           *
+           * @memberOf platform.os
+           * @type String|Null
+           */
+          'family': null,
+
+          /**
+           * The version of the OS.
+           *
+           * @memberOf platform.os
+           * @type String|Null
+           */
+          'version': null,
+
+          /**
+           * Returns the OS string.
+           *
+           * @memberOf platform.os
+           * @returns {String} The OS string.
+           */
+          'toString': function() { return 'null'; }
+        },
+
+      /**
+       * The platform description.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'description': description.length ? description.join(' ') : ua,
+
+      /**
+       * The name of the browser layout engine.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'layout': layout && layout[0],
+
+      /**
+       * The name of the product's manufacturer.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'manufacturer': manufacturer,
+
+      /**
+       * The alpha/beta release indicator.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'prerelease': prerelease,
+
+      /**
+       * The name of the product hosting the browser.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'product': product,
+
+      /**
+       * The browser's user agent string.
+       *
+       * @memberOf platform
+       * @type String|Null
+       */
+      'ua': ua,
+
+      // parses a user agent string into a platform object
+      'parse': parse,
+
+      // returns the platform description
+      'toString': toStringPlatform
+    };
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose platform
+  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // define as an anonymous module so, through path mapping, it can be aliased
+    define(function() {
+      return parse();
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports) {
+    // in Narwhal, Node.js, or RingoJS
+    forOwn(parse(), function(value, key) {
+      freeExports[key] = value;
+    });
+  }
+  // in a browser or Rhino
+  else {
+    // use square bracket notation so Closure Compiler won't munge `platform`
+    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
+    window['platform'] = parse();
+  }
+}(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/LICENSE.txt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/LICENSE.txt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/LICENSE.txt	(revision 533)
@@ -0,0 +1,20 @@
+Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/README.md	(revision 533)
@@ -0,0 +1,58 @@
+# QUnit CLIB <sup>v1.2.0</sup>
+## command-line interface boilerplate
+
+QUnit CLIB helps extend QUnit's CLI support to many common CLI environments.
+
+## Screenshot
+
+![QUnit CLIB brings QUnit to your favorite shell.](http://i.imgur.com/jpu9l.png)
+
+## Support
+
+QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.19, Narwhal v0.3.2, PhantomJS 1.8.1, RingoJS v0.9, and Rhino v1.7RC5.
+
+## Usage
+
+```js
+(function(window) {
+
+  // use a single "load" function
+  var load = typeof require == 'function' ? require : window.load;
+
+  // load QUnit and CLIB if needed
+  var QUnit =
+    window.QUnit || (
+      window.addEventListener || (window.addEventListener = Function.prototype),
+      window.setTimeout || (window.setTimeout = Function.prototype),
+      window.QUnit = load('path/to/qunit.js') || window.QUnit,
+      load('path/to/qunit-clib.js'),
+      window.addEventListener === Function.prototype && delete window.addEventListener,
+      window.QUnit
+    );
+
+  // explicitly call `QUnit.module()` instead of `module()`
+  // in case we are in a CLI environment
+  QUnit.module('A Test Module');
+
+  test('A Test', function() {
+    // ...
+  });
+
+  // must call `QUnit.start()` if using QUnit < 1.3.0 with Node.js or any
+  // version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
+  if (!window.document) {
+    QUnit.start();
+  }
+}(typeof global == 'object' && global || this));
+```
+
+## Footnotes
+
+  1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
+
+  2. Rhino v1.7RC4 does not support timeout fallbacks `clearTimeout` and `setTimeout`
+
+## Author
+
+* [John-David Dalton](http://allyoucanleet.com/)
+  [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/qunit-clib.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/qunit-clib.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/qunit-clib.js	(revision 533)
@@ -0,0 +1,269 @@
+/*!
+ * QUnit CLI Boilerplate v1.2.0
+ * Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
+ * Based on a gist by JÃ¶rn Zaefferer <https://gist.github.com/722381>
+ * Available under MIT license <http://mths.be/mit>
+ */
+;(function(window) {
+  'use strict';
+
+  /**
+   * Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
+   * https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
+   * http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
+   */
+  (function() {
+
+    /**
+     * Schedules timer-based callbacks.
+     *
+     * @private
+     * @param {Function|String} fn The function to call.
+     * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
+     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
+     * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
+     * @returns {Number} The the ID of the timeout.
+     */
+    function schedule(fn, delay, args, repeated) {
+      // Rhino 1.7RC4 will error assigning `task` below
+      // https://bugzilla.mozilla.org/show_bug.cgi?id=775566
+      var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
+        'run': function() {
+          fn.apply(window, args);
+        }
+      });
+      // support non-functions
+      if (typeof fn != 'function') {
+        fn = (function(code) {
+          code = String(code);
+          return function() { eval(code); };
+        }(fn));
+      }
+      // used by setInterval
+      if (repeated) {
+        timer.schedule(task, delay, delay);
+      }
+      // used by setTimeout
+      else {
+        timer.schedule(task, delay);
+      }
+      return counter;
+    }
+
+    /**
+     * Clears the delay set by `setInterval` or `setTimeout`.
+     *
+     * @memberOf window
+     * @param {Number} id The ID of the timeout to be cleared.
+     */
+    function clearTimer(id) {
+      if (ids[id]) {
+        ids[id].cancel();
+        timer.purge();
+        delete ids[id];
+      }
+    }
+
+    /**
+     * Executes a code snippet or function repeatedly, with a delay between each call.
+     *
+     * @memberOf window
+     * @param {Function|String} fn The function to call or string to evaluate.
+     * @oaram {Number} delay The number of milliseconds to delay each `fn` call.
+     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
+     * @returns {Number} The the ID of the timeout.
+     */
+    function setInterval(fn, delay) {
+      return schedule(fn, delay, slice.call(arguments, 2), true);
+    }
+
+    /**
+     * Executes a code snippet or a function after specified delay.
+     *
+     * @memberOf window
+     * @param {Function|String} fn The function to call or string to evaluate.
+     * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
+     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
+     * @returns {Number} The the ID of the timeout.
+     */
+    function setTimeout(fn, delay) {
+      return schedule(fn, delay, slice.call(arguments, 2));
+    }
+
+    try {
+      var counter = 0,
+          ids = {},
+          slice = Array.prototype.slice,
+          timer = new java.util.Timer;
+
+      window.clearInterval =
+      window.clearTimeout = clearTimer;
+      window.setInterval = setInterval;
+      window.setTimeout = setTimeout;
+    } catch(e) { }
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  (function() {
+
+    /** Used as a horizontal rule in console output */
+    var hr = '----------------------------------------';
+
+    /** Shorten `window.QUnit.QUnit` to `window.QUnit` */
+    window.QUnit && (QUnit = QUnit.QUnit || QUnit);
+
+    /**
+     * A logging callback triggered when all testing is completed.
+     *
+     * @memberOf QUnit
+     * @param {Object} details An object with properties `failed`, `passed`, `runtime`, and `total`.
+     */
+    QUnit.done(function() {
+      var ran;
+      return function(details) {
+        // stop `asyncTest()` from erroneously calling `done()` twice in
+        // environments w/o timeouts
+        if (ran) {
+          return;
+        }
+        ran = true;
+
+        console.log(hr);
+        console.log('    PASS: ' + details.passed + '  FAIL: ' + details.failed + '  TOTAL: ' + details.total);
+        console.log('    Finished in ' + details.runtime + ' milliseconds.');
+        console.log(hr);
+
+        // exit out of Rhino
+        try {
+          quit();
+        } catch(e) { }
+
+        // exit out of Node.js or PhantomJS
+        try {
+          var process = window.process || window.phantom;
+          if (details.failed) {
+            console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
+            process.exit(1);
+          } else {
+            process.exit(0);
+          }
+        } catch(e) { }
+      };
+    }());
+
+    /**
+     * A logging callback triggered after every assertion.
+     *
+     * @memberOf QUnit
+     * @param {Object} details An object with properties `actual`, `expected`, `message`, and `result`.
+     */
+    QUnit.log(function(details) {
+      var expected = details.expected,
+          result = details.result,
+          type = typeof expected != 'undefined' ? 'EQ' : 'OK';
+
+      var assertion = [
+        result ? 'PASS' : 'FAIL',
+        type,
+        details.message || 'ok'
+      ];
+
+      if (!result && type == 'EQ') {
+        assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
+      }
+      QUnit.config.testStats.assertions.push(assertion.join(' | '));
+    });
+
+    /**
+     * A logging callback triggered at the start of every test module.
+     *
+     * @memberOf QUnit
+     * @param {Object} details An object with property `name`.
+     */
+    QUnit.moduleStart(function(details) {
+      console.log(hr);
+      console.log(details.name);
+      console.log(hr);
+    });
+
+    /**
+     * Converts an object into a string representation.
+     *
+     * @memberOf QUnit
+     * @type Function
+     * @param {Object} object The object to stringify.
+     * @returns {String} The result string.
+     */
+    QUnit.jsDump.parsers.object = (function() {
+      var func = QUnit.jsDump.parsers.object;
+      return function(object) {
+        // fork to support Rhino's error objects
+        if (typeof object.rhinoException == 'object') {
+          return object.name +
+            ' { message: "' + object.message +
+            '", fileName: "' + object.fileName +
+            '", lineNumber: ' + object.lineNumber + ' }';
+        }
+        return func(object);
+      };
+    }());
+
+    /**
+     * A logging callback triggered after a test is completed.
+     *
+     * @memberOf QUnit
+     * @param {Object} details An object with properties `failed`, `name`, `passed`, and `total`.
+     */
+    QUnit.testDone(function(details) {
+      var assertions = QUnit.config.testStats.assertions,
+          testName = details.name;
+
+      if (details.failed > 0) {
+        console.log(' FAIL - '+ testName);
+        assertions.forEach(function(value) {
+          console.log('    ' + value);
+        });
+      }
+      else {
+        console.log(' PASS - ' + testName);
+      }
+      assertions.length = 0;
+    });
+
+    /**
+     * An object used to hold information about the current running test.
+     *
+     * @memberOf QUnit.config
+     * @type Object
+     */
+    QUnit.config.testStats = {
+
+      /**
+       * An array of test summaries (pipe separated).
+       *
+       * @memberOf QUnit.config.testStats
+       * @type Array
+       */
+      'assertions': []
+    };
+  }());
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose shortcuts
+  // exclude `module` because some environments have it as a built-in object
+  ('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' +
+   'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) {
+    window[methodName] = QUnit[methodName];
+  });
+
+  // add `console.log()` support for Narwhal, Rhino, and RingoJS
+  if (!window.console && window.print) {
+    window.console = { 'log': window.print };
+  }
+  // must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
+  // Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
+  QUnit.init();
+
+}(typeof global == 'object' && global || this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/README.md	(revision 533)
@@ -0,0 +1,62 @@
+[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework.
+================================
+
+QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
+project to test its code and plugins but is capable of testing any generic
+JavaScript code (and even capable of testing JavaScript code on the server-side).
+
+QUnit is especially useful for regression testing: Whenever a bug is reported,
+write a test that asserts the existence of that particular bug. Then fix it and
+commit both. Every time you work on the code again, run the tests. If the bug
+comes up again - a regression - you'll spot it immediately and know how to fix
+it, because you know what code you just changed.
+
+Having good unit test coverage makes safe refactoring easy and cheap. You can
+run the tests after each small refactoring step and always know what change
+broke something.
+
+QUnit is similar to other unit testing frameworks like JUnit, but makes use of
+the features JavaScript provides and helps with testing code in the browser, e.g.
+with its stop/start facilities for testing asynchronous code.
+
+If you are interested in helping developing QUnit, you are in the right place.
+For related discussions, visit the
+[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing).
+
+Development
+-----------
+
+To submit patches, fork the repository, create a branch for the change. Then implement
+the change, run `grunt` to lint and test it, then commit, push and create a pull request.
+
+Include some background for the change in the commit message and `Fixes #nnn`, referring
+to the issue number you're addressing.
+
+To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global
+grunt binary. For additional grunt tasks, also run `npm install`.
+
+Releases
+--------
+
+Install git-extras and run `git changelog` to update History.md.
+Update qunit/qunit.js|css and package.json to the release version, commit and
+tag, update them again to the next version, commit and push commits and tags
+(`git push --tags origin master`).
+
+Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
+or whitespace cleanups.
+
+To upload to code.jquery.com (replace $version accordingly), ssh to code.origin.jquery.com:
+
+	cp qunit/qunit.js /var/www/html/code.jquery.com/qunit/qunit-$version.js
+	cp qunit/qunit.css /var/www/html/code.jquery.com/qunit/qunit-$version.css
+
+Then update /var/www/html/code.jquery.com/index.html and purge it with:
+
+	curl -s http://code.origin.jquery.com/?reload
+
+Update web-base-template to link to those files for qunitjs.com.
+
+Publish to npm via
+
+	npm publish
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/qunit/qunit.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/qunit/qunit.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/qunit/qunit.js	(revision 533)
@@ -0,0 +1,2152 @@
+/**
+ * QUnit v1.11.0 - A JavaScript Unit Testing Framework
+ *
+ * http://qunitjs.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+(function( window ) {
+
+var QUnit,
+	assert,
+	config,
+	onErrorFnPrev,
+	testId = 0,
+	fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
+	toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty,
+	// Keep a local reference to Date (GH-283)
+	Date = window.Date,
+	defined = {
+		setTimeout: typeof window.setTimeout !== "undefined",
+		sessionStorage: (function() {
+			var x = "qunit-test-string";
+			try {
+				sessionStorage.setItem( x, x );
+				sessionStorage.removeItem( x );
+				return true;
+			} catch( e ) {
+				return false;
+			}
+		}())
+	},
+	/**
+	 * Provides a normalized error string, correcting an issue
+	 * with IE 7 (and prior) where Error.prototype.toString is
+	 * not properly implemented
+	 *
+	 * Based on http://es5.github.com/#x15.11.4.4
+	 *
+	 * @param {String|Error} error
+	 * @return {String} error message
+	 */
+	errorString = function( error ) {
+		var name, message,
+			errorString = error.toString();
+		if ( errorString.substring( 0, 7 ) === "[object" ) {
+			name = error.name ? error.name.toString() : "Error";
+			message = error.message ? error.message.toString() : "";
+			if ( name && message ) {
+				return name + ": " + message;
+			} else if ( name ) {
+				return name;
+			} else if ( message ) {
+				return message;
+			} else {
+				return "Error";
+			}
+		} else {
+			return errorString;
+		}
+	},
+	/**
+	 * Makes a clone of an object using only Array or Object as base,
+	 * and copies over the own enumerable properties.
+	 *
+	 * @param {Object} obj
+	 * @return {Object} New object with only the own properties (recursively).
+	 */
+	objectValues = function( obj ) {
+		// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
+		/*jshint newcap: false */
+		var key, val,
+			vals = QUnit.is( "array", obj ) ? [] : {};
+		for ( key in obj ) {
+			if ( hasOwn.call( obj, key ) ) {
+				val = obj[key];
+				vals[key] = val === Object(val) ? objectValues(val) : val;
+			}
+		}
+		return vals;
+	};
+
+function Test( settings ) {
+	extend( this, settings );
+	this.assertions = [];
+	this.testNumber = ++Test.count;
+}
+
+Test.count = 0;
+
+Test.prototype = {
+	init: function() {
+		var a, b, li,
+			tests = id( "qunit-tests" );
+
+		if ( tests ) {
+			b = document.createElement( "strong" );
+			b.innerHTML = this.nameHtml;
+
+			// `a` initialized at top of scope
+			a = document.createElement( "a" );
+			a.innerHTML = "Rerun";
+			a.href = QUnit.url({ testNumber: this.testNumber });
+
+			li = document.createElement( "li" );
+			li.appendChild( b );
+			li.appendChild( a );
+			li.className = "running";
+			li.id = this.id = "qunit-test-output" + testId++;
+
+			tests.appendChild( li );
+		}
+	},
+	setup: function() {
+		if ( this.module !== config.previousModule ) {
+			if ( config.previousModule ) {
+				runLoggingCallbacks( "moduleDone", QUnit, {
+					name: config.previousModule,
+					failed: config.moduleStats.bad,
+					passed: config.moduleStats.all - config.moduleStats.bad,
+					total: config.moduleStats.all
+				});
+			}
+			config.previousModule = this.module;
+			config.moduleStats = { all: 0, bad: 0 };
+			runLoggingCallbacks( "moduleStart", QUnit, {
+				name: this.module
+			});
+		} else if ( config.autorun ) {
+			runLoggingCallbacks( "moduleStart", QUnit, {
+				name: this.module
+			});
+		}
+
+		config.current = this;
+
+		this.testEnvironment = extend({
+			setup: function() {},
+			teardown: function() {}
+		}, this.moduleTestEnvironment );
+
+		this.started = +new Date();
+		runLoggingCallbacks( "testStart", QUnit, {
+			name: this.testName,
+			module: this.module
+		});
+
+		// allow utility functions to access the current test environment
+		// TODO why??
+		QUnit.current_testEnvironment = this.testEnvironment;
+
+		if ( !config.pollution ) {
+			saveGlobal();
+		}
+		if ( config.notrycatch ) {
+			this.testEnvironment.setup.call( this.testEnvironment );
+			return;
+		}
+		try {
+			this.testEnvironment.setup.call( this.testEnvironment );
+		} catch( e ) {
+			QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+		}
+	},
+	run: function() {
+		config.current = this;
+
+		var running = id( "qunit-testresult" );
+
+		if ( running ) {
+			running.innerHTML = "Running: <br/>" + this.nameHtml;
+		}
+
+		if ( this.async ) {
+			QUnit.stop();
+		}
+
+		this.callbackStarted = +new Date();
+
+		if ( config.notrycatch ) {
+			this.callback.call( this.testEnvironment, QUnit.assert );
+			this.callbackRuntime = +new Date() - this.callbackStarted;
+			return;
+		}
+
+		try {
+			this.callback.call( this.testEnvironment, QUnit.assert );
+			this.callbackRuntime = +new Date() - this.callbackStarted;
+		} catch( e ) {
+			this.callbackRuntime = +new Date() - this.callbackStarted;
+
+			QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
+			// else next test will carry the responsibility
+			saveGlobal();
+
+			// Restart the tests if they're blocking
+			if ( config.blocking ) {
+				QUnit.start();
+			}
+		}
+	},
+	teardown: function() {
+		config.current = this;
+		if ( config.notrycatch ) {
+			if ( typeof this.callbackRuntime === "undefined" ) {
+				this.callbackRuntime = +new Date() - this.callbackStarted;
+			}
+			this.testEnvironment.teardown.call( this.testEnvironment );
+			return;
+		} else {
+			try {
+				this.testEnvironment.teardown.call( this.testEnvironment );
+			} catch( e ) {
+				QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+			}
+		}
+		checkPollution();
+	},
+	finish: function() {
+		config.current = this;
+		if ( config.requireExpects && this.expected === null ) {
+			QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
+		} else if ( this.expected !== null && this.expected !== this.assertions.length ) {
+			QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
+		} else if ( this.expected === null && !this.assertions.length ) {
+			QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
+		}
+
+		var i, assertion, a, b, time, li, ol,
+			test = this,
+			good = 0,
+			bad = 0,
+			tests = id( "qunit-tests" );
+
+		this.runtime = +new Date() - this.started;
+		config.stats.all += this.assertions.length;
+		config.moduleStats.all += this.assertions.length;
+
+		if ( tests ) {
+			ol = document.createElement( "ol" );
+			ol.className = "qunit-assert-list";
+
+			for ( i = 0; i < this.assertions.length; i++ ) {
+				assertion = this.assertions[i];
+
+				li = document.createElement( "li" );
+				li.className = assertion.result ? "pass" : "fail";
+				li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
+				ol.appendChild( li );
+
+				if ( assertion.result ) {
+					good++;
+				} else {
+					bad++;
+					config.stats.bad++;
+					config.moduleStats.bad++;
+				}
+			}
+
+			// store result when possible
+			if ( QUnit.config.reorder && defined.sessionStorage ) {
+				if ( bad ) {
+					sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
+				} else {
+					sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
+				}
+			}
+
+			if ( bad === 0 ) {
+				addClass( ol, "qunit-collapsed" );
+			}
+
+			// `b` initialized at top of scope
+			b = document.createElement( "strong" );
+			b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
+
+			addEvent(b, "click", function() {
+				var next = b.parentNode.lastChild,
+					collapsed = hasClass( next, "qunit-collapsed" );
+				( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
+			});
+
+			addEvent(b, "dblclick", function( e ) {
+				var target = e && e.target ? e.target : window.event.srcElement;
+				if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
+					target = target.parentNode;
+				}
+				if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
+					window.location = QUnit.url({ testNumber: test.testNumber });
+				}
+			});
+
+			// `time` initialized at top of scope
+			time = document.createElement( "span" );
+			time.className = "runtime";
+			time.innerHTML = this.runtime + " ms";
+
+			// `li` initialized at top of scope
+			li = id( this.id );
+			li.className = bad ? "fail" : "pass";
+			li.removeChild( li.firstChild );
+			a = li.firstChild;
+			li.appendChild( b );
+			li.appendChild( a );
+			li.appendChild( time );
+			li.appendChild( ol );
+
+		} else {
+			for ( i = 0; i < this.assertions.length; i++ ) {
+				if ( !this.assertions[i].result ) {
+					bad++;
+					config.stats.bad++;
+					config.moduleStats.bad++;
+				}
+			}
+		}
+
+		runLoggingCallbacks( "testDone", QUnit, {
+			name: this.testName,
+			module: this.module,
+			failed: bad,
+			passed: this.assertions.length - bad,
+			total: this.assertions.length,
+			duration: this.runtime
+		});
+
+		QUnit.reset();
+
+		config.current = undefined;
+	},
+
+	queue: function() {
+		var bad,
+			test = this;
+
+		synchronize(function() {
+			test.init();
+		});
+		function run() {
+			// each of these can by async
+			synchronize(function() {
+				test.setup();
+			});
+			synchronize(function() {
+				test.run();
+			});
+			synchronize(function() {
+				test.teardown();
+			});
+			synchronize(function() {
+				test.finish();
+			});
+		}
+
+		// `bad` initialized at top of scope
+		// defer when previous test run passed, if storage is available
+		bad = QUnit.config.reorder && defined.sessionStorage &&
+						+sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
+
+		if ( bad ) {
+			run();
+		} else {
+			synchronize( run, true );
+		}
+	}
+};
+
+// Root QUnit object.
+// `QUnit` initialized at top of scope
+QUnit = {
+
+	// call on start of module test to prepend name to all tests
+	module: function( name, testEnvironment ) {
+		config.currentModule = name;
+		config.currentModuleTestEnvironment = testEnvironment;
+		config.modules[name] = true;
+	},
+
+	asyncTest: function( testName, expected, callback ) {
+		if ( arguments.length === 2 ) {
+			callback = expected;
+			expected = null;
+		}
+
+		QUnit.test( testName, expected, callback, true );
+	},
+
+	test: function( testName, expected, callback, async ) {
+		var test,
+			nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
+
+		if ( arguments.length === 2 ) {
+			callback = expected;
+			expected = null;
+		}
+
+		if ( config.currentModule ) {
+			nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
+		}
+
+		test = new Test({
+			nameHtml: nameHtml,
+			testName: testName,
+			expected: expected,
+			async: async,
+			callback: callback,
+			module: config.currentModule,
+			moduleTestEnvironment: config.currentModuleTestEnvironment,
+			stack: sourceFromStacktrace( 2 )
+		});
+
+		if ( !validTest( test ) ) {
+			return;
+		}
+
+		test.queue();
+	},
+
+	// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
+	expect: function( asserts ) {
+		if (arguments.length === 1) {
+			config.current.expected = asserts;
+		} else {
+			return config.current.expected;
+		}
+	},
+
+	start: function( count ) {
+		// QUnit hasn't been initialized yet.
+		// Note: RequireJS (et al) may delay onLoad
+		if ( config.semaphore === undefined ) {
+			QUnit.begin(function() {
+				// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
+				setTimeout(function() {
+					QUnit.start( count );
+				});
+			});
+			return;
+		}
+
+		config.semaphore -= count || 1;
+		// don't start until equal number of stop-calls
+		if ( config.semaphore > 0 ) {
+			return;
+		}
+		// ignore if start is called more often then stop
+		if ( config.semaphore < 0 ) {
+			config.semaphore = 0;
+			QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
+			return;
+		}
+		// A slight delay, to avoid any current callbacks
+		if ( defined.setTimeout ) {
+			window.setTimeout(function() {
+				if ( config.semaphore > 0 ) {
+					return;
+				}
+				if ( config.timeout ) {
+					clearTimeout( config.timeout );
+				}
+
+				config.blocking = false;
+				process( true );
+			}, 13);
+		} else {
+			config.blocking = false;
+			process( true );
+		}
+	},
+
+	stop: function( count ) {
+		config.semaphore += count || 1;
+		config.blocking = true;
+
+		if ( config.testTimeout && defined.setTimeout ) {
+			clearTimeout( config.timeout );
+			config.timeout = window.setTimeout(function() {
+				QUnit.ok( false, "Test timed out" );
+				config.semaphore = 1;
+				QUnit.start();
+			}, config.testTimeout );
+		}
+	}
+};
+
+// `assert` initialized at top of scope
+// Asssert helpers
+// All of these must either call QUnit.push() or manually do:
+// - runLoggingCallbacks( "log", .. );
+// - config.current.assertions.push({ .. });
+// We attach it to the QUnit object *after* we expose the public API,
+// otherwise `assert` will become a global variable in browsers (#341).
+assert = {
+	/**
+	 * Asserts rough true-ish result.
+	 * @name ok
+	 * @function
+	 * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
+	 */
+	ok: function( result, msg ) {
+		if ( !config.current ) {
+			throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
+		}
+		result = !!result;
+
+		var source,
+			details = {
+				module: config.current.module,
+				name: config.current.testName,
+				result: result,
+				message: msg
+			};
+
+		msg = escapeText( msg || (result ? "okay" : "failed" ) );
+		msg = "<span class='test-message'>" + msg + "</span>";
+
+		if ( !result ) {
+			source = sourceFromStacktrace( 2 );
+			if ( source ) {
+				details.source = source;
+				msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
+			}
+		}
+		runLoggingCallbacks( "log", QUnit, details );
+		config.current.assertions.push({
+			result: result,
+			message: msg
+		});
+	},
+
+	/**
+	 * Assert that the first two arguments are equal, with an optional message.
+	 * Prints out both actual and expected values.
+	 * @name equal
+	 * @function
+	 * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
+	 */
+	equal: function( actual, expected, message ) {
+		/*jshint eqeqeq:false */
+		QUnit.push( expected == actual, actual, expected, message );
+	},
+
+	/**
+	 * @name notEqual
+	 * @function
+	 */
+	notEqual: function( actual, expected, message ) {
+		/*jshint eqeqeq:false */
+		QUnit.push( expected != actual, actual, expected, message );
+	},
+
+	/**
+	 * @name propEqual
+	 * @function
+	 */
+	propEqual: function( actual, expected, message ) {
+		actual = objectValues(actual);
+		expected = objectValues(expected);
+		QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+	},
+
+	/**
+	 * @name notPropEqual
+	 * @function
+	 */
+	notPropEqual: function( actual, expected, message ) {
+		actual = objectValues(actual);
+		expected = objectValues(expected);
+		QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+	},
+
+	/**
+	 * @name deepEqual
+	 * @function
+	 */
+	deepEqual: function( actual, expected, message ) {
+		QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+	},
+
+	/**
+	 * @name notDeepEqual
+	 * @function
+	 */
+	notDeepEqual: function( actual, expected, message ) {
+		QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+	},
+
+	/**
+	 * @name strictEqual
+	 * @function
+	 */
+	strictEqual: function( actual, expected, message ) {
+		QUnit.push( expected === actual, actual, expected, message );
+	},
+
+	/**
+	 * @name notStrictEqual
+	 * @function
+	 */
+	notStrictEqual: function( actual, expected, message ) {
+		QUnit.push( expected !== actual, actual, expected, message );
+	},
+
+	"throws": function( block, expected, message ) {
+		var actual,
+			expectedOutput = expected,
+			ok = false;
+
+		// 'expected' is optional
+		if ( typeof expected === "string" ) {
+			message = expected;
+			expected = null;
+		}
+
+		config.current.ignoreGlobalErrors = true;
+		try {
+			block.call( config.current.testEnvironment );
+		} catch (e) {
+			actual = e;
+		}
+		config.current.ignoreGlobalErrors = false;
+
+		if ( actual ) {
+			// we don't want to validate thrown error
+			if ( !expected ) {
+				ok = true;
+				expectedOutput = null;
+			// expected is a regexp
+			} else if ( QUnit.objectType( expected ) === "regexp" ) {
+				ok = expected.test( errorString( actual ) );
+			// expected is a constructor
+			} else if ( actual instanceof expected ) {
+				ok = true;
+			// expected is a validation function which returns true is validation passed
+			} else if ( expected.call( {}, actual ) === true ) {
+				expectedOutput = null;
+				ok = true;
+			}
+
+			QUnit.push( ok, actual, expectedOutput, message );
+		} else {
+			QUnit.pushFailure( message, null, 'No exception was thrown.' );
+		}
+	}
+};
+
+/**
+ * @deprecate since 1.8.0
+ * Kept assertion helpers in root for backwards compatibility.
+ */
+extend( QUnit, assert );
+
+/**
+ * @deprecated since 1.9.0
+ * Kept root "raises()" for backwards compatibility.
+ * (Note that we don't introduce assert.raises).
+ */
+QUnit.raises = assert[ "throws" ];
+
+/**
+ * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
+ * Kept to avoid TypeErrors for undefined methods.
+ */
+QUnit.equals = function() {
+	QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
+};
+QUnit.same = function() {
+	QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
+};
+
+// We want access to the constructor's prototype
+(function() {
+	function F() {}
+	F.prototype = QUnit;
+	QUnit = new F();
+	// Make F QUnit's constructor so that we can add to the prototype later
+	QUnit.constructor = F;
+}());
+
+/**
+ * Config object: Maintain internal state
+ * Later exposed as QUnit.config
+ * `config` initialized at top of scope
+ */
+config = {
+	// The queue of tests to run
+	queue: [],
+
+	// block until document ready
+	blocking: true,
+
+	// when enabled, show only failing tests
+	// gets persisted through sessionStorage and can be changed in UI via checkbox
+	hidepassed: false,
+
+	// by default, run previously failed tests first
+	// very useful in combination with "Hide passed tests" checked
+	reorder: true,
+
+	// by default, modify document.title when suite is done
+	altertitle: true,
+
+	// when enabled, all tests must call expect()
+	requireExpects: false,
+
+	// add checkboxes that are persisted in the query-string
+	// when enabled, the id is set to `true` as a `QUnit.config` property
+	urlConfig: [
+		{
+			id: "noglobals",
+			label: "Check for Globals",
+			tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
+		},
+		{
+			id: "notrycatch",
+			label: "No try-catch",
+			tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
+		}
+	],
+
+	// Set of all modules.
+	modules: {},
+
+	// logging callback queues
+	begin: [],
+	done: [],
+	log: [],
+	testStart: [],
+	testDone: [],
+	moduleStart: [],
+	moduleDone: []
+};
+
+// Export global variables, unless an 'exports' object exists,
+// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
+if ( typeof exports === "undefined" ) {
+	extend( window, QUnit );
+
+	// Expose QUnit object
+	window.QUnit = QUnit;
+}
+
+// Initialize more QUnit.config and QUnit.urlParams
+(function() {
+	var i,
+		location = window.location || { search: "", protocol: "file:" },
+		params = location.search.slice( 1 ).split( "&" ),
+		length = params.length,
+		urlParams = {},
+		current;
+
+	if ( params[ 0 ] ) {
+		for ( i = 0; i < length; i++ ) {
+			current = params[ i ].split( "=" );
+			current[ 0 ] = decodeURIComponent( current[ 0 ] );
+			// allow just a key to turn on a flag, e.g., test.html?noglobals
+			current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
+			urlParams[ current[ 0 ] ] = current[ 1 ];
+		}
+	}
+
+	QUnit.urlParams = urlParams;
+
+	// String search anywhere in moduleName+testName
+	config.filter = urlParams.filter;
+
+	// Exact match of the module name
+	config.module = urlParams.module;
+
+	config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
+
+	// Figure out if we're running the tests from a server or not
+	QUnit.isLocal = location.protocol === "file:";
+}());
+
+// Extend QUnit object,
+// these after set here because they should not be exposed as global functions
+extend( QUnit, {
+	assert: assert,
+
+	config: config,
+
+	// Initialize the configuration options
+	init: function() {
+		extend( config, {
+			stats: { all: 0, bad: 0 },
+			moduleStats: { all: 0, bad: 0 },
+			started: +new Date(),
+			updateRate: 1000,
+			blocking: false,
+			autostart: true,
+			autorun: false,
+			filter: "",
+			queue: [],
+			semaphore: 1
+		});
+
+		var tests, banner, result,
+			qunit = id( "qunit" );
+
+		if ( qunit ) {
+			qunit.innerHTML =
+				"<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+				"<h2 id='qunit-banner'></h2>" +
+				"<div id='qunit-testrunner-toolbar'></div>" +
+				"<h2 id='qunit-userAgent'></h2>" +
+				"<ol id='qunit-tests'></ol>";
+		}
+
+		tests = id( "qunit-tests" );
+		banner = id( "qunit-banner" );
+		result = id( "qunit-testresult" );
+
+		if ( tests ) {
+			tests.innerHTML = "";
+		}
+
+		if ( banner ) {
+			banner.className = "";
+		}
+
+		if ( result ) {
+			result.parentNode.removeChild( result );
+		}
+
+		if ( tests ) {
+			result = document.createElement( "p" );
+			result.id = "qunit-testresult";
+			result.className = "result";
+			tests.parentNode.insertBefore( result, tests );
+			result.innerHTML = "Running...<br/>&nbsp;";
+		}
+	},
+
+	// Resets the test setup. Useful for tests that modify the DOM.
+	reset: function() {
+		var fixture = id( "qunit-fixture" );
+		if ( fixture ) {
+			fixture.innerHTML = config.fixture;
+		}
+	},
+
+	// Trigger an event on an element.
+	// @example triggerEvent( document.body, "click" );
+	triggerEvent: function( elem, type, event ) {
+		if ( document.createEvent ) {
+			event = document.createEvent( "MouseEvents" );
+			event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
+				0, 0, 0, 0, 0, false, false, false, false, 0, null);
+
+			elem.dispatchEvent( event );
+		} else if ( elem.fireEvent ) {
+			elem.fireEvent( "on" + type );
+		}
+	},
+
+	// Safe object type checking
+	is: function( type, obj ) {
+		return QUnit.objectType( obj ) === type;
+	},
+
+	objectType: function( obj ) {
+		if ( typeof obj === "undefined" ) {
+				return "undefined";
+		// consider: typeof null === object
+		}
+		if ( obj === null ) {
+				return "null";
+		}
+
+		var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
+			type = match && match[1] || "";
+
+		switch ( type ) {
+			case "Number":
+				if ( isNaN(obj) ) {
+					return "nan";
+				}
+				return "number";
+			case "String":
+			case "Boolean":
+			case "Array":
+			case "Date":
+			case "RegExp":
+			case "Function":
+				return type.toLowerCase();
+		}
+		if ( typeof obj === "object" ) {
+			return "object";
+		}
+		return undefined;
+	},
+
+	push: function( result, actual, expected, message ) {
+		if ( !config.current ) {
+			throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
+		}
+
+		var output, source,
+			details = {
+				module: config.current.module,
+				name: config.current.testName,
+				result: result,
+				message: message,
+				actual: actual,
+				expected: expected
+			};
+
+		message = escapeText( message ) || ( result ? "okay" : "failed" );
+		message = "<span class='test-message'>" + message + "</span>";
+		output = message;
+
+		if ( !result ) {
+			expected = escapeText( QUnit.jsDump.parse(expected) );
+			actual = escapeText( QUnit.jsDump.parse(actual) );
+			output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
+
+			if ( actual !== expected ) {
+				output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
+				output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
+			}
+
+			source = sourceFromStacktrace();
+
+			if ( source ) {
+				details.source = source;
+				output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+			}
+
+			output += "</table>";
+		}
+
+		runLoggingCallbacks( "log", QUnit, details );
+
+		config.current.assertions.push({
+			result: !!result,
+			message: output
+		});
+	},
+
+	pushFailure: function( message, source, actual ) {
+		if ( !config.current ) {
+			throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
+		}
+
+		var output,
+			details = {
+				module: config.current.module,
+				name: config.current.testName,
+				result: false,
+				message: message
+			};
+
+		message = escapeText( message ) || "error";
+		message = "<span class='test-message'>" + message + "</span>";
+		output = message;
+
+		output += "<table>";
+
+		if ( actual ) {
+			output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
+		}
+
+		if ( source ) {
+			details.source = source;
+			output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+		}
+
+		output += "</table>";
+
+		runLoggingCallbacks( "log", QUnit, details );
+
+		config.current.assertions.push({
+			result: false,
+			message: output
+		});
+	},
+
+	url: function( params ) {
+		params = extend( extend( {}, QUnit.urlParams ), params );
+		var key,
+			querystring = "?";
+
+		for ( key in params ) {
+			if ( !hasOwn.call( params, key ) ) {
+				continue;
+			}
+			querystring += encodeURIComponent( key ) + "=" +
+				encodeURIComponent( params[ key ] ) + "&";
+		}
+		return window.location.protocol + "//" + window.location.host +
+			window.location.pathname + querystring.slice( 0, -1 );
+	},
+
+	extend: extend,
+	id: id,
+	addEvent: addEvent
+	// load, equiv, jsDump, diff: Attached later
+});
+
+/**
+ * @deprecated: Created for backwards compatibility with test runner that set the hook function
+ * into QUnit.{hook}, instead of invoking it and passing the hook function.
+ * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
+ * Doing this allows us to tell if the following methods have been overwritten on the actual
+ * QUnit object.
+ */
+extend( QUnit.constructor.prototype, {
+
+	// Logging callbacks; all receive a single argument with the listed properties
+	// run test/logs.html for any related changes
+	begin: registerLoggingCallback( "begin" ),
+
+	// done: { failed, passed, total, runtime }
+	done: registerLoggingCallback( "done" ),
+
+	// log: { result, actual, expected, message }
+	log: registerLoggingCallback( "log" ),
+
+	// testStart: { name }
+	testStart: registerLoggingCallback( "testStart" ),
+
+	// testDone: { name, failed, passed, total, duration }
+	testDone: registerLoggingCallback( "testDone" ),
+
+	// moduleStart: { name }
+	moduleStart: registerLoggingCallback( "moduleStart" ),
+
+	// moduleDone: { name, failed, passed, total }
+	moduleDone: registerLoggingCallback( "moduleDone" )
+});
+
+if ( typeof document === "undefined" || document.readyState === "complete" ) {
+	config.autorun = true;
+}
+
+QUnit.load = function() {
+	runLoggingCallbacks( "begin", QUnit, {} );
+
+	// Initialize the config, saving the execution queue
+	var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
+		urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
+		numModules = 0,
+		moduleFilterHtml = "",
+		urlConfigHtml = "",
+		oldconfig = extend( {}, config );
+
+	QUnit.init();
+	extend(config, oldconfig);
+
+	config.blocking = false;
+
+	len = config.urlConfig.length;
+
+	for ( i = 0; i < len; i++ ) {
+		val = config.urlConfig[i];
+		if ( typeof val === "string" ) {
+			val = {
+				id: val,
+				label: val,
+				tooltip: "[no tooltip available]"
+			};
+		}
+		config[ val.id ] = QUnit.urlParams[ val.id ];
+		urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
+			"' name='" + escapeText( val.id ) +
+			"' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
+			" title='" + escapeText( val.tooltip ) +
+			"'><label for='qunit-urlconfig-" + escapeText( val.id ) +
+			"' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
+	}
+
+	moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+		( config.module === undefined  ? "selected='selected'" : "" ) +
+		">< All Modules ></option>";
+
+	for ( i in config.modules ) {
+		if ( config.modules.hasOwnProperty( i ) ) {
+			numModules += 1;
+			moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
+				( config.module === i ? "selected='selected'" : "" ) +
+				">" + escapeText(i) + "</option>";
+		}
+	}
+	moduleFilterHtml += "</select>";
+
+	// `userAgent` initialized at top of scope
+	userAgent = id( "qunit-userAgent" );
+	if ( userAgent ) {
+		userAgent.innerHTML = navigator.userAgent;
+	}
+
+	// `banner` initialized at top of scope
+	banner = id( "qunit-header" );
+	if ( banner ) {
+		banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
+	}
+
+	// `toolbar` initialized at top of scope
+	toolbar = id( "qunit-testrunner-toolbar" );
+	if ( toolbar ) {
+		// `filter` initialized at top of scope
+		filter = document.createElement( "input" );
+		filter.type = "checkbox";
+		filter.id = "qunit-filter-pass";
+
+		addEvent( filter, "click", function() {
+			var tmp,
+				ol = document.getElementById( "qunit-tests" );
+
+			if ( filter.checked ) {
+				ol.className = ol.className + " hidepass";
+			} else {
+				tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
+				ol.className = tmp.replace( / hidepass /, " " );
+			}
+			if ( defined.sessionStorage ) {
+				if (filter.checked) {
+					sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
+				} else {
+					sessionStorage.removeItem( "qunit-filter-passed-tests" );
+				}
+			}
+		});
+
+		if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
+			filter.checked = true;
+			// `ol` initialized at top of scope
+			ol = document.getElementById( "qunit-tests" );
+			ol.className = ol.className + " hidepass";
+		}
+		toolbar.appendChild( filter );
+
+		// `label` initialized at top of scope
+		label = document.createElement( "label" );
+		label.setAttribute( "for", "qunit-filter-pass" );
+		label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
+		label.innerHTML = "Hide passed tests";
+		toolbar.appendChild( label );
+
+		urlConfigCheckboxesContainer = document.createElement("span");
+		urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
+		urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
+		// For oldIE support:
+		// * Add handlers to the individual elements instead of the container
+		// * Use "click" instead of "change"
+		// * Fallback from event.target to event.srcElement
+		addEvents( urlConfigCheckboxes, "click", function( event ) {
+			var params = {},
+				target = event.target || event.srcElement;
+			params[ target.name ] = target.checked ? true : undefined;
+			window.location = QUnit.url( params );
+		});
+		toolbar.appendChild( urlConfigCheckboxesContainer );
+
+		if (numModules > 1) {
+			moduleFilter = document.createElement( 'span' );
+			moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
+			moduleFilter.innerHTML = moduleFilterHtml;
+			addEvent( moduleFilter.lastChild, "change", function() {
+				var selectBox = moduleFilter.getElementsByTagName("select")[0],
+					selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+
+				window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
+			});
+			toolbar.appendChild(moduleFilter);
+		}
+	}
+
+	// `main` initialized at top of scope
+	main = id( "qunit-fixture" );
+	if ( main ) {
+		config.fixture = main.innerHTML;
+	}
+
+	if ( config.autostart ) {
+		QUnit.start();
+	}
+};
+
+addEvent( window, "load", QUnit.load );
+
+// `onErrorFnPrev` initialized at top of scope
+// Preserve other handlers
+onErrorFnPrev = window.onerror;
+
+// Cover uncaught exceptions
+// Returning true will surpress the default browser handler,
+// returning false will let it run.
+window.onerror = function ( error, filePath, linerNr ) {
+	var ret = false;
+	if ( onErrorFnPrev ) {
+		ret = onErrorFnPrev( error, filePath, linerNr );
+	}
+
+	// Treat return value as window.onerror itself does,
+	// Only do our handling if not surpressed.
+	if ( ret !== true ) {
+		if ( QUnit.config.current ) {
+			if ( QUnit.config.current.ignoreGlobalErrors ) {
+				return true;
+			}
+			QUnit.pushFailure( error, filePath + ":" + linerNr );
+		} else {
+			QUnit.test( "global failure", extend( function() {
+				QUnit.pushFailure( error, filePath + ":" + linerNr );
+			}, { validTest: validTest } ) );
+		}
+		return false;
+	}
+
+	return ret;
+};
+
+function done() {
+	config.autorun = true;
+
+	// Log the last module results
+	if ( config.currentModule ) {
+		runLoggingCallbacks( "moduleDone", QUnit, {
+			name: config.currentModule,
+			failed: config.moduleStats.bad,
+			passed: config.moduleStats.all - config.moduleStats.bad,
+			total: config.moduleStats.all
+		});
+	}
+
+	var i, key,
+		banner = id( "qunit-banner" ),
+		tests = id( "qunit-tests" ),
+		runtime = +new Date() - config.started,
+		passed = config.stats.all - config.stats.bad,
+		html = [
+			"Tests completed in ",
+			runtime,
+			" milliseconds.<br/>",
+			"<span class='passed'>",
+			passed,
+			"</span> assertions of <span class='total'>",
+			config.stats.all,
+			"</span> passed, <span class='failed'>",
+			config.stats.bad,
+			"</span> failed."
+		].join( "" );
+
+	if ( banner ) {
+		banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
+	}
+
+	if ( tests ) {
+		id( "qunit-testresult" ).innerHTML = html;
+	}
+
+	if ( config.altertitle && typeof document !== "undefined" && document.title ) {
+		// show â for good, â for bad suite result in title
+		// use escape sequences in case file gets loaded with non-utf-8-charset
+		document.title = [
+			( config.stats.bad ? "\u2716" : "\u2714" ),
+			document.title.replace( /^[\u2714\u2716] /i, "" )
+		].join( " " );
+	}
+
+	// clear own sessionStorage items if all tests passed
+	if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
+		// `key` & `i` initialized at top of scope
+		for ( i = 0; i < sessionStorage.length; i++ ) {
+			key = sessionStorage.key( i++ );
+			if ( key.indexOf( "qunit-test-" ) === 0 ) {
+				sessionStorage.removeItem( key );
+			}
+		}
+	}
+
+	// scroll back to top to show results
+	if ( window.scrollTo ) {
+		window.scrollTo(0, 0);
+	}
+
+	runLoggingCallbacks( "done", QUnit, {
+		failed: config.stats.bad,
+		passed: passed,
+		total: config.stats.all,
+		runtime: runtime
+	});
+}
+
+/** @return Boolean: true if this test should be ran */
+function validTest( test ) {
+	var include,
+		filter = config.filter && config.filter.toLowerCase(),
+		module = config.module && config.module.toLowerCase(),
+		fullName = (test.module + ": " + test.testName).toLowerCase();
+
+	// Internally-generated tests are always valid
+	if ( test.callback && test.callback.validTest === validTest ) {
+		delete test.callback.validTest;
+		return true;
+	}
+
+	if ( config.testNumber ) {
+		return test.testNumber === config.testNumber;
+	}
+
+	if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
+		return false;
+	}
+
+	if ( !filter ) {
+		return true;
+	}
+
+	include = filter.charAt( 0 ) !== "!";
+	if ( !include ) {
+		filter = filter.slice( 1 );
+	}
+
+	// If the filter matches, we need to honour include
+	if ( fullName.indexOf( filter ) !== -1 ) {
+		return include;
+	}
+
+	// Otherwise, do the opposite
+	return !include;
+}
+
+// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
+// Later Safari and IE10 are supposed to support error.stack as well
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+function extractStacktrace( e, offset ) {
+	offset = offset === undefined ? 3 : offset;
+
+	var stack, include, i;
+
+	if ( e.stacktrace ) {
+		// Opera
+		return e.stacktrace.split( "\n" )[ offset + 3 ];
+	} else if ( e.stack ) {
+		// Firefox, Chrome
+		stack = e.stack.split( "\n" );
+		if (/^error$/i.test( stack[0] ) ) {
+			stack.shift();
+		}
+		if ( fileName ) {
+			include = [];
+			for ( i = offset; i < stack.length; i++ ) {
+				if ( stack[ i ].indexOf( fileName ) !== -1 ) {
+					break;
+				}
+				include.push( stack[ i ] );
+			}
+			if ( include.length ) {
+				return include.join( "\n" );
+			}
+		}
+		return stack[ offset ];
+	} else if ( e.sourceURL ) {
+		// Safari, PhantomJS
+		// hopefully one day Safari provides actual stacktraces
+		// exclude useless self-reference for generated Error objects
+		if ( /qunit.js$/.test( e.sourceURL ) ) {
+			return;
+		}
+		// for actual exceptions, this is useful
+		return e.sourceURL + ":" + e.line;
+	}
+}
+function sourceFromStacktrace( offset ) {
+	try {
+		throw new Error();
+	} catch ( e ) {
+		return extractStacktrace( e, offset );
+	}
+}
+
+/**
+ * Escape text for attribute or text content.
+ */
+function escapeText( s ) {
+	if ( !s ) {
+		return "";
+	}
+	s = s + "";
+	// Both single quotes and double quotes (for attributes)
+	return s.replace( /['"<>&]/g, function( s ) {
+		switch( s ) {
+			case '\'':
+				return '&#039;';
+			case '"':
+				return '&quot;';
+			case '<':
+				return '&lt;';
+			case '>':
+				return '&gt;';
+			case '&':
+				return '&amp;';
+		}
+	});
+}
+
+function synchronize( callback, last ) {
+	config.queue.push( callback );
+
+	if ( config.autorun && !config.blocking ) {
+		process( last );
+	}
+}
+
+function process( last ) {
+	function next() {
+		process( last );
+	}
+	var start = new Date().getTime();
+	config.depth = config.depth ? config.depth + 1 : 1;
+
+	while ( config.queue.length && !config.blocking ) {
+		if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
+			config.queue.shift()();
+		} else {
+			window.setTimeout( next, 13 );
+			break;
+		}
+	}
+	config.depth--;
+	if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
+		done();
+	}
+}
+
+function saveGlobal() {
+	config.pollution = [];
+
+	if ( config.noglobals ) {
+		for ( var key in window ) {
+			// in Opera sometimes DOM element ids show up here, ignore them
+			if ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) {
+				continue;
+			}
+			config.pollution.push( key );
+		}
+	}
+}
+
+function checkPollution() {
+	var newGlobals,
+		deletedGlobals,
+		old = config.pollution;
+
+	saveGlobal();
+
+	newGlobals = diff( config.pollution, old );
+	if ( newGlobals.length > 0 ) {
+		QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
+	}
+
+	deletedGlobals = diff( old, config.pollution );
+	if ( deletedGlobals.length > 0 ) {
+		QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
+	}
+}
+
+// returns a new Array with the elements that are in a but not in b
+function diff( a, b ) {
+	var i, j,
+		result = a.slice();
+
+	for ( i = 0; i < result.length; i++ ) {
+		for ( j = 0; j < b.length; j++ ) {
+			if ( result[i] === b[j] ) {
+				result.splice( i, 1 );
+				i--;
+				break;
+			}
+		}
+	}
+	return result;
+}
+
+function extend( a, b ) {
+	for ( var prop in b ) {
+		if ( b[ prop ] === undefined ) {
+			delete a[ prop ];
+
+		// Avoid "Member not found" error in IE8 caused by setting window.constructor
+		} else if ( prop !== "constructor" || a !== window ) {
+			a[ prop ] = b[ prop ];
+		}
+	}
+
+	return a;
+}
+
+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
+	// Standards-based browsers
+	if ( elem.addEventListener ) {
+		elem.addEventListener( type, fn, false );
+	// IE
+	} else {
+		elem.attachEvent( "on" + type, fn );
+	}
+}
+
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+	var i = elems.length;
+	while ( i-- ) {
+		addEvent( elems[i], type, fn );
+	}
+}
+
+function hasClass( elem, name ) {
+	return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
+}
+
+function addClass( elem, name ) {
+	if ( !hasClass( elem, name ) ) {
+		elem.className += (elem.className ? " " : "") + name;
+	}
+}
+
+function removeClass( elem, name ) {
+	var set = " " + elem.className + " ";
+	// Class name may appear multiple times
+	while ( set.indexOf(" " + name + " ") > -1 ) {
+		set = set.replace(" " + name + " " , " ");
+	}
+	// If possible, trim it for prettiness, but not neccecarily
+	elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
+}
+
+function id( name ) {
+	return !!( typeof document !== "undefined" && document && document.getElementById ) &&
+		document.getElementById( name );
+}
+
+function registerLoggingCallback( key ) {
+	return function( callback ) {
+		config[key].push( callback );
+	};
+}
+
+// Supports deprecated method of completely overwriting logging callbacks
+function runLoggingCallbacks( key, scope, args ) {
+	var i, callbacks;
+	if ( QUnit.hasOwnProperty( key ) ) {
+		QUnit[ key ].call(scope, args );
+	} else {
+		callbacks = config[ key ];
+		for ( i = 0; i < callbacks.length; i++ ) {
+			callbacks[ i ].call( scope, args );
+		}
+	}
+}
+
+// Test for equality any JavaScript type.
+// Author: Philippe RathÃ© <prathe@gmail.com>
+QUnit.equiv = (function() {
+
+	// Call the o related callback with the given arguments.
+	function bindCallbacks( o, callbacks, args ) {
+		var prop = QUnit.objectType( o );
+		if ( prop ) {
+			if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
+				return callbacks[ prop ].apply( callbacks, args );
+			} else {
+				return callbacks[ prop ]; // or undefined
+			}
+		}
+	}
+
+	// the real equiv function
+	var innerEquiv,
+		// stack to decide between skip/abort functions
+		callers = [],
+		// stack to avoiding loops from circular referencing
+		parents = [],
+
+		getProto = Object.getPrototypeOf || function ( obj ) {
+			return obj.__proto__;
+		},
+		callbacks = (function () {
+
+			// for string, boolean, number and null
+			function useStrictEquality( b, a ) {
+				/*jshint eqeqeq:false */
+				if ( b instanceof a.constructor || a instanceof b.constructor ) {
+					// to catch short annotaion VS 'new' annotation of a
+					// declaration
+					// e.g. var i = 1;
+					// var j = new Number(1);
+					return a == b;
+				} else {
+					return a === b;
+				}
+			}
+
+			return {
+				"string": useStrictEquality,
+				"boolean": useStrictEquality,
+				"number": useStrictEquality,
+				"null": useStrictEquality,
+				"undefined": useStrictEquality,
+
+				"nan": function( b ) {
+					return isNaN( b );
+				},
+
+				"date": function( b, a ) {
+					return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
+				},
+
+				"regexp": function( b, a ) {
+					return QUnit.objectType( b ) === "regexp" &&
+						// the regex itself
+						a.source === b.source &&
+						// and its modifers
+						a.global === b.global &&
+						// (gmi) ...
+						a.ignoreCase === b.ignoreCase &&
+						a.multiline === b.multiline &&
+						a.sticky === b.sticky;
+				},
+
+				// - skip when the property is a method of an instance (OOP)
+				// - abort otherwise,
+				// initial === would have catch identical references anyway
+				"function": function() {
+					var caller = callers[callers.length - 1];
+					return caller !== Object && typeof caller !== "undefined";
+				},
+
+				"array": function( b, a ) {
+					var i, j, len, loop;
+
+					// b could be an object literal here
+					if ( QUnit.objectType( b ) !== "array" ) {
+						return false;
+					}
+
+					len = a.length;
+					if ( len !== b.length ) {
+						// safe and faster
+						return false;
+					}
+
+					// track reference to avoid circular references
+					parents.push( a );
+					for ( i = 0; i < len; i++ ) {
+						loop = false;
+						for ( j = 0; j < parents.length; j++ ) {
+							if ( parents[j] === a[i] ) {
+								loop = true;// dont rewalk array
+							}
+						}
+						if ( !loop && !innerEquiv(a[i], b[i]) ) {
+							parents.pop();
+							return false;
+						}
+					}
+					parents.pop();
+					return true;
+				},
+
+				"object": function( b, a ) {
+					var i, j, loop,
+						// Default to true
+						eq = true,
+						aProperties = [],
+						bProperties = [];
+
+					// comparing constructors is more strict than using
+					// instanceof
+					if ( a.constructor !== b.constructor ) {
+						// Allow objects with no prototype to be equivalent to
+						// objects with Object as their constructor.
+						if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
+							( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
+								return false;
+						}
+					}
+
+					// stack constructor before traversing properties
+					callers.push( a.constructor );
+					// track reference to avoid circular references
+					parents.push( a );
+
+					for ( i in a ) { // be strict: don't ensures hasOwnProperty
+									// and go deep
+						loop = false;
+						for ( j = 0; j < parents.length; j++ ) {
+							if ( parents[j] === a[i] ) {
+								// don't go down the same path twice
+								loop = true;
+							}
+						}
+						aProperties.push(i); // collect a's properties
+
+						if (!loop && !innerEquiv( a[i], b[i] ) ) {
+							eq = false;
+							break;
+						}
+					}
+
+					callers.pop(); // unstack, we are done
+					parents.pop();
+
+					for ( i in b ) {
+						bProperties.push( i ); // collect b's properties
+					}
+
+					// Ensures identical properties name
+					return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
+				}
+			};
+		}());
+
+	innerEquiv = function() { // can take multiple arguments
+		var args = [].slice.apply( arguments );
+		if ( args.length < 2 ) {
+			return true; // end transition
+		}
+
+		return (function( a, b ) {
+			if ( a === b ) {
+				return true; // catch the most you can
+			} else if ( a === null || b === null || typeof a === "undefined" ||
+					typeof b === "undefined" ||
+					QUnit.objectType(a) !== QUnit.objectType(b) ) {
+				return false; // don't lose time with error prone cases
+			} else {
+				return bindCallbacks(a, callbacks, [ b, a ]);
+			}
+
+			// apply transition with (1..n) arguments
+		}( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) );
+	};
+
+	return innerEquiv;
+}());
+
+/**
+ * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
+ * http://flesler.blogspot.com Licensed under BSD
+ * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
+ *
+ * @projectDescription Advanced and extensible data dumping for Javascript.
+ * @version 1.0.0
+ * @author Ariel Flesler
+ * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
+ */
+QUnit.jsDump = (function() {
+	function quote( str ) {
+		return '"' + str.toString().replace( /"/g, '\\"' ) + '"';
+	}
+	function literal( o ) {
+		return o + "";
+	}
+	function join( pre, arr, post ) {
+		var s = jsDump.separator(),
+			base = jsDump.indent(),
+			inner = jsDump.indent(1);
+		if ( arr.join ) {
+			arr = arr.join( "," + s + inner );
+		}
+		if ( !arr ) {
+			return pre + post;
+		}
+		return [ pre, inner + arr, base + post ].join(s);
+	}
+	function array( arr, stack ) {
+		var i = arr.length, ret = new Array(i);
+		this.up();
+		while ( i-- ) {
+			ret[i] = this.parse( arr[i] , undefined , stack);
+		}
+		this.down();
+		return join( "[", ret, "]" );
+	}
+
+	var reName = /^function (\w+)/,
+		jsDump = {
+			// type is used mostly internally, you can fix a (custom)type in advance
+			parse: function( obj, type, stack ) {
+				stack = stack || [ ];
+				var inStack, res,
+					parser = this.parsers[ type || this.typeOf(obj) ];
+
+				type = typeof parser;
+				inStack = inArray( obj, stack );
+
+				if ( inStack !== -1 ) {
+					return "recursion(" + (inStack - stack.length) + ")";
+				}
+				if ( type === "function" )  {
+					stack.push( obj );
+					res = parser.call( this, obj, stack );
+					stack.pop();
+					return res;
+				}
+				return ( type === "string" ) ? parser : this.parsers.error;
+			},
+			typeOf: function( obj ) {
+				var type;
+				if ( obj === null ) {
+					type = "null";
+				} else if ( typeof obj === "undefined" ) {
+					type = "undefined";
+				} else if ( QUnit.is( "regexp", obj) ) {
+					type = "regexp";
+				} else if ( QUnit.is( "date", obj) ) {
+					type = "date";
+				} else if ( QUnit.is( "function", obj) ) {
+					type = "function";
+				} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
+					type = "window";
+				} else if ( obj.nodeType === 9 ) {
+					type = "document";
+				} else if ( obj.nodeType ) {
+					type = "node";
+				} else if (
+					// native arrays
+					toString.call( obj ) === "[object Array]" ||
+					// NodeList objects
+					( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
+				) {
+					type = "array";
+				} else if ( obj.constructor === Error.prototype.constructor ) {
+					type = "error";
+				} else {
+					type = typeof obj;
+				}
+				return type;
+			},
+			separator: function() {
+				return this.multiline ?	this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
+			},
+			// extra can be a number, shortcut for increasing-calling-decreasing
+			indent: function( extra ) {
+				if ( !this.multiline ) {
+					return "";
+				}
+				var chr = this.indentChar;
+				if ( this.HTML ) {
+					chr = chr.replace( /\t/g, "   " ).replace( / /g, "&nbsp;" );
+				}
+				return new Array( this._depth_ + (extra||0) ).join(chr);
+			},
+			up: function( a ) {
+				this._depth_ += a || 1;
+			},
+			down: function( a ) {
+				this._depth_ -= a || 1;
+			},
+			setParser: function( name, parser ) {
+				this.parsers[name] = parser;
+			},
+			// The next 3 are exposed so you can use them
+			quote: quote,
+			literal: literal,
+			join: join,
+			//
+			_depth_: 1,
+			// This is the list of parsers, to modify them, use jsDump.setParser
+			parsers: {
+				window: "[Window]",
+				document: "[Document]",
+				error: function(error) {
+					return "Error(\"" + error.message + "\")";
+				},
+				unknown: "[Unknown]",
+				"null": "null",
+				"undefined": "undefined",
+				"function": function( fn ) {
+					var ret = "function",
+						// functions never have name in IE
+						name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
+
+					if ( name ) {
+						ret += " " + name;
+					}
+					ret += "( ";
+
+					ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
+					return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
+				},
+				array: array,
+				nodelist: array,
+				"arguments": array,
+				object: function( map, stack ) {
+					var ret = [ ], keys, key, val, i;
+					QUnit.jsDump.up();
+					keys = [];
+					for ( key in map ) {
+						keys.push( key );
+					}
+					keys.sort();
+					for ( i = 0; i < keys.length; i++ ) {
+						key = keys[ i ];
+						val = map[ key ];
+						ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
+					}
+					QUnit.jsDump.down();
+					return join( "{", ret, "}" );
+				},
+				node: function( node ) {
+					var len, i, val,
+						open = QUnit.jsDump.HTML ? "&lt;" : "<",
+						close = QUnit.jsDump.HTML ? "&gt;" : ">",
+						tag = node.nodeName.toLowerCase(),
+						ret = open + tag,
+						attrs = node.attributes;
+
+					if ( attrs ) {
+						for ( i = 0, len = attrs.length; i < len; i++ ) {
+							val = attrs[i].nodeValue;
+							// IE6 includes all attributes in .attributes, even ones not explicitly set.
+							// Those have values like undefined, null, 0, false, "" or "inherit".
+							if ( val && val !== "inherit" ) {
+								ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
+							}
+						}
+					}
+					ret += close;
+
+					// Show content of TextNode or CDATASection
+					if ( node.nodeType === 3 || node.nodeType === 4 ) {
+						ret += node.nodeValue;
+					}
+
+					return ret + open + "/" + tag + close;
+				},
+				// function calls it internally, it's the arguments part of the function
+				functionArgs: function( fn ) {
+					var args,
+						l = fn.length;
+
+					if ( !l ) {
+						return "";
+					}
+
+					args = new Array(l);
+					while ( l-- ) {
+						// 97 is 'a'
+						args[l] = String.fromCharCode(97+l);
+					}
+					return " " + args.join( ", " ) + " ";
+				},
+				// object calls it internally, the key part of an item in a map
+				key: quote,
+				// function calls it internally, it's the content of the function
+				functionCode: "[code]",
+				// node calls it internally, it's an html attribute value
+				attribute: quote,
+				string: quote,
+				date: quote,
+				regexp: literal,
+				number: literal,
+				"boolean": literal
+			},
+			// if true, entities are escaped ( <, >, \t, space and \n )
+			HTML: false,
+			// indentation unit
+			indentChar: "  ",
+			// if true, items in a collection, are separated by a \n, else just a space.
+			multiline: true
+		};
+
+	return jsDump;
+}());
+
+// from jquery.js
+function inArray( elem, array ) {
+	if ( array.indexOf ) {
+		return array.indexOf( elem );
+	}
+
+	for ( var i = 0, length = array.length; i < length; i++ ) {
+		if ( array[ i ] === elem ) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+/*
+ * Javascript Diff Algorithm
+ *  By John Resig (http://ejohn.org/)
+ *  Modified by Chu Alan "sprite"
+ *
+ * Released under the MIT license.
+ *
+ * More Info:
+ *  http://ejohn.org/projects/javascript-diff-algorithm/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
+ */
+QUnit.diff = (function() {
+	/*jshint eqeqeq:false, eqnull:true */
+	function diff( o, n ) {
+		var i,
+			ns = {},
+			os = {};
+
+		for ( i = 0; i < n.length; i++ ) {
+			if ( !hasOwn.call( ns, n[i] ) ) {
+				ns[ n[i] ] = {
+					rows: [],
+					o: null
+				};
+			}
+			ns[ n[i] ].rows.push( i );
+		}
+
+		for ( i = 0; i < o.length; i++ ) {
+			if ( !hasOwn.call( os, o[i] ) ) {
+				os[ o[i] ] = {
+					rows: [],
+					n: null
+				};
+			}
+			os[ o[i] ].rows.push( i );
+		}
+
+		for ( i in ns ) {
+			if ( !hasOwn.call( ns, i ) ) {
+				continue;
+			}
+			if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
+				n[ ns[i].rows[0] ] = {
+					text: n[ ns[i].rows[0] ],
+					row: os[i].rows[0]
+				};
+				o[ os[i].rows[0] ] = {
+					text: o[ os[i].rows[0] ],
+					row: ns[i].rows[0]
+				};
+			}
+		}
+
+		for ( i = 0; i < n.length - 1; i++ ) {
+			if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
+						n[ i + 1 ] == o[ n[i].row + 1 ] ) {
+
+				n[ i + 1 ] = {
+					text: n[ i + 1 ],
+					row: n[i].row + 1
+				};
+				o[ n[i].row + 1 ] = {
+					text: o[ n[i].row + 1 ],
+					row: i + 1
+				};
+			}
+		}
+
+		for ( i = n.length - 1; i > 0; i-- ) {
+			if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
+						n[ i - 1 ] == o[ n[i].row - 1 ]) {
+
+				n[ i - 1 ] = {
+					text: n[ i - 1 ],
+					row: n[i].row - 1
+				};
+				o[ n[i].row - 1 ] = {
+					text: o[ n[i].row - 1 ],
+					row: i - 1
+				};
+			}
+		}
+
+		return {
+			o: o,
+			n: n
+		};
+	}
+
+	return function( o, n ) {
+		o = o.replace( /\s+$/, "" );
+		n = n.replace( /\s+$/, "" );
+
+		var i, pre,
+			str = "",
+			out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
+			oSpace = o.match(/\s+/g),
+			nSpace = n.match(/\s+/g);
+
+		if ( oSpace == null ) {
+			oSpace = [ " " ];
+		}
+		else {
+			oSpace.push( " " );
+		}
+
+		if ( nSpace == null ) {
+			nSpace = [ " " ];
+		}
+		else {
+			nSpace.push( " " );
+		}
+
+		if ( out.n.length === 0 ) {
+			for ( i = 0; i < out.o.length; i++ ) {
+				str += "<del>" + out.o[i] + oSpace[i] + "</del>";
+			}
+		}
+		else {
+			if ( out.n[0].text == null ) {
+				for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
+					str += "<del>" + out.o[n] + oSpace[n] + "</del>";
+				}
+			}
+
+			for ( i = 0; i < out.n.length; i++ ) {
+				if (out.n[i].text == null) {
+					str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
+				}
+				else {
+					// `pre` initialized at top of scope
+					pre = "";
+
+					for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
+						pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
+					}
+					str += " " + out.n[i].text + nSpace[i] + pre;
+				}
+			}
+		}
+
+		return str;
+	};
+}());
+
+// for CommonJS enviroments, export everything
+if ( typeof exports !== "undefined" ) {
+	extend( exports, QUnit );
+}
+
+// get at whatever the global object is, like window in browsers
+}( (function() {return this;}.call()) ));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/README.md	(revision 533)
@@ -0,0 +1,50 @@
+# node-tar
+
+Tar for Node.js.
+
+## Goals of this project
+
+1. Be able to parse and reasonably extract the contents of any tar file
+   created by any program that creates tar files, period.
+
+    At least, this includes every version of:
+
+    * bsdtar
+    * gnutar
+    * solaris posix tar
+    * Joerg Schilling's star ("Schilly tar")
+
+2. Create tar files that can be extracted by any of the following tar
+   programs:
+
+    * bsdtar/libarchive version 2.6.2
+    * gnutar 1.15 and above
+    * SunOS Posix tar
+    * Joerg Schilling's star ("Schilly tar")
+
+3. 100% test coverage.  Speed is important.  Correctness is slightly
+   more important.
+
+4. Create the kind of tar interface that Node users would want to use.
+
+5. Satisfy npm's needs for a portable tar implementation with a
+   JavaScript interface.
+
+6. No excuses.  No complaining.  No tolerance for failure.
+
+## But isn't there already a tar.js?
+
+Yes, there are a few.  This one is going to be better, and it will be
+fanatically maintained, because npm will depend on it.
+
+That's why I need to write it from scratch.  Creating and extracting
+tarballs is such a large part of what npm does, I simply can't have it
+be a black box any longer.
+
+## Didn't you have something already?  Where'd it go?
+
+It's in the "old" folder.  It's not functional.  Don't use it.
+
+It was a useful exploration to learn the issues involved, but like most
+software of any reasonable complexity, node-tar won't be useful until
+it's been written at least 3 times.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/buffer-entry.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/buffer-entry.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/buffer-entry.js	(revision 533)
@@ -0,0 +1,30 @@
+// just like the Entry class, but it buffers the contents
+//
+// XXX It would be good to set a maximum BufferEntry filesize,
+// since it eats up memory.  In normal operation,
+// these are only for long filenames or link names, which are
+// rarely very big.
+
+module.exports = BufferEntry
+
+var inherits = require("../vendor/inherits/inherits.js")
+  , Entry = require("./entry.js")
+
+function BufferEntry () {
+  Entry.apply(this, arguments)
+  this._buffer = new Buffer(this.props.size)
+  this._offset = 0
+  this.body = ""
+  this.on("end", function () {
+    this.body = this._buffer.toString().slice(0, -1)
+  })
+}
+
+// collect the bytes as they come in.
+BufferEntry.prototype.write = function (c) {
+  c.copy(this._buffer, this._offset)
+  this._offset += c.length
+  Entry.prototype.write.call(this, c)
+}
+
+inherits(BufferEntry, Entry)
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry-writer.js	(revision 533)
@@ -0,0 +1,169 @@
+module.exports = EntryWriter
+
+var tar = require("../tar.js")
+  , TarHeader = require("./header.js")
+  , Entry = require("./entry.js")
+  , inherits = require("../vendor/inherits/inherits.js")
+  , BlockStream = require("../vendor/block-stream/block-stream.js")
+  , ExtendedHeaderWriter
+  , Stream = require("stream").Stream
+  , EOF = {}
+
+inherits(EntryWriter, Stream)
+
+function EntryWriter (props) {
+  var me = this
+
+  if (!(me instanceof EntryWriter)) {
+    return new EntryWriter(props)
+  }
+
+  Stream.apply(this)
+
+  me.writable = true
+  me.readable = true
+
+  me._stream = new BlockStream(512)
+
+  me._stream.on("data", function (c) {
+    me.emit("data", c)
+  })
+
+  me._stream.on("drain", function () {
+    me.emit("drain")
+  })
+
+  me._stream.on("end", function () {
+    me.emit("end")
+    me.emit("close")
+  })
+
+  me.props = props
+  if (props.type === "Directory") {
+    props.size = 0
+  }
+  props.ustar = "ustar\0"
+  props.ustarver = "00"
+  me.path = props.path
+
+  me._buffer = []
+  me._didHeader = false
+  me._meta = false
+
+  me.on("pipe", function () {
+    me._process()
+  })
+}
+
+EntryWriter.prototype.write = function (c) {
+  // console.error(".. ew write")
+  if (this._ended) return this.emit("error", new Error("write after end"))
+  this._buffer.push(c)
+  this._process()
+  this._needDrain = this._buffer.length > 0
+  return !this._needDrain
+}
+
+EntryWriter.prototype.end = function (c) {
+  // console.error(".. ew end")
+  if (c) this._buffer.push(c)
+  this._buffer.push(EOF)
+  this._ended = true
+  this._process()
+  this._needDrain = this._buffer.length > 0
+}
+
+EntryWriter.prototype.pause = function () {
+  // console.error(".. ew pause")
+  this._paused = true
+  this.emit("pause")
+}
+
+EntryWriter.prototype.resume = function () {
+  // console.error(".. ew resume")
+  this._paused = false
+  this.emit("resume")
+  this._process()
+}
+
+EntryWriter.prototype.add = function (entry) {
+  // console.error(".. ew add")
+  if (!this.parent) return this.emit("error", new Error("no parent"))
+
+  // make sure that the _header and such is emitted, and clear out
+  // the _currentEntry link on the parent.
+  if (!this._ended) this.end()
+
+  return this.parent.add(entry)
+}
+
+EntryWriter.prototype._header = function () {
+  // console.error(".. ew header")
+  if (this._didHeader) return
+  this._didHeader = true
+
+  var headerBlock = TarHeader.encode(this.props)
+
+  if (this.props.needExtended && !this._meta) {
+    var me = this
+
+    ExtendedHeaderWriter = ExtendedHeaderWriter ||
+      require("./extended-header-writer.js")
+
+    ExtendedHeaderWriter(this.props)
+      .on("data", function (c) {
+        me.emit("data", c)
+      })
+      .on("error", function (er) {
+        me.emit("error", er)
+      })
+      .end()
+  }
+
+  // console.error(".. .. ew headerBlock emitting")
+  this.emit("data", headerBlock)
+  this.emit("header")
+}
+
+EntryWriter.prototype._process = function () {
+  // console.error(".. .. ew process")
+  if (!this._didHeader && !this._meta) {
+    this._header()
+  }
+
+  if (this._paused || this._processing) {
+    // console.error(".. .. .. paused=%j, processing=%j", this._paused, this._processing)
+    return
+  }
+
+  this._processing = true
+
+  var buf = this._buffer
+  for (var i = 0; i < buf.length; i ++) {
+    // console.error(".. .. .. i=%d", i)
+
+    var c = buf[i]
+
+    if (c === EOF) this._stream.end()
+    else this._stream.write(c)
+
+    if (this._paused) {
+      // console.error(".. .. .. paused mid-emission")
+      this._processing = false
+      if (i < buf.length) {
+        this._needDrain = true
+        this._buffer = buf.slice(i + 1)
+      }
+      return
+    }
+  }
+
+  // console.error(".. .. .. emitted")
+  this._buffer.length = 0
+  this._processing = false
+
+  // console.error(".. .. .. emitting drain")
+  this.emit("drain")
+}
+
+EntryWriter.prototype.destroy = function () {}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry.js	(revision 533)
@@ -0,0 +1,212 @@
+// A passthrough read/write stream that sets its properties
+// based on a header, extendedHeader, and globalHeader
+//
+// Can be either a file system object of some sort, or
+// a pax/ustar metadata entry.
+
+module.exports = Entry
+
+var TarHeader = require("./header.js")
+  , tar = require("../tar")
+  , assert = require("assert").ok
+  , Stream = require("stream").Stream
+  , inherits = require("../vendor/inherits/inherits.js")
+  , fstream = require("../vendor/fstream/fstream.js").Abstract
+
+function Entry (header, extended, global) {
+  Stream.call(this)
+  this.readable = true
+  this.writable = true
+
+  this._needDrain = false
+  this._paused = false
+  this._reading = false
+  this._ending = false
+  this._ended = false
+  this._remaining = 0
+  this._queue = []
+  this._index = 0
+  this._queueLen = 0
+
+  this._read = this._read.bind(this)
+
+  this.props = {}
+  this._header = header
+  this._extended = extended || {}
+
+  // globals can change throughout the course of
+  // a file parse operation.  Freeze it at its current state.
+  this._global = {}
+  var me = this
+  Object.keys(global || {}).forEach(function (g) {
+    me._global[g] = global[g]
+  })
+
+  this._setProps()
+}
+
+inherits(Entry, Stream,
+{ write: function (c) {
+    if (this._ending) this.error("write() after end()", null, true)
+    if (this._remaining === 0) {
+      this.error("invalid bytes past eof")
+    }
+
+    // often we'll get a bunch of \0 at the end of the last write,
+    // since chunks will always be 512 bytes when reading a tarball.
+    if (c.length > this._remaining) {
+      c = c.slice(0, this._remaining)
+    }
+    this._remaining -= c.length
+
+    // put it on the stack.
+    var ql = this._queueLen
+    this._queue.push(c)
+    this._queueLen ++
+
+    this._read()
+
+    // either paused, or buffered
+    if (this._paused || ql > 0) {
+      this._needDrain = true
+      return false
+    }
+
+    return true
+  }
+
+, end: function (c) {
+    if (c) this.write(c)
+    this._ending = true
+    this._read()
+  }
+
+, pause: function () {
+    this._paused = true
+    this.emit("pause")
+  }
+
+, resume: function () {
+    // console.error("    Tar Entry resume", this.path)
+    this.emit("resume")
+    this._paused = false
+    this._read()
+    return this._queueLen - this._index > 1
+  }
+
+  // This is bound to the instance
+, _read: function () {
+    // console.error("    Tar Entry _read", this.path)
+
+    if (this._paused || this._reading || this._ended) return
+
+    // set this flag so that event handlers don't inadvertently
+    // get multiple _read() calls running.
+    this._reading = true
+
+    // have any data to emit?
+    if (this._index < this._queueLen) {
+      var chunk = this._queue[this._index ++]
+      this.emit("data", chunk)
+    }
+
+    // check if we're drained
+    if (this._index >= this._queueLen) {
+      this._queue.length = this._queueLen = this._index = 0
+      if (this._needDrain) {
+        this._needDrain = false
+        this.emit("drain")
+      }
+      if (this._ending) {
+        this._ended = true
+        this.emit("end")
+      }
+    }
+
+    // if the queue gets too big, then pluck off whatever we can.
+    // this should be fairly rare.
+    var mql = this._maxQueueLen
+    if (this._queueLen > mql && this._index > 0) {
+      mql = Math.min(this._index, mql)
+      this._index -= mql
+      this._queueLen -= mql
+      this._queue = this._queue.slice(mql)
+    }
+
+    this._reading = false
+  }
+
+, _setProps: function () {
+    // props = extended->global->header->{}
+    var header = this._header
+      , extended = this._extended
+      , global = this._global
+      , props = this.props
+
+    // first get the values from the normal header.
+    var fields = tar.fields
+    for (var f = 0; fields[f] !== null; f ++) {
+      var field = fields[f]
+        , val = header[field]
+      if (typeof val !== "undefined") props[field] = val
+    }
+
+    // next, the global header for this file.
+    // numeric values, etc, will have already been parsed.
+    ;[global, extended].forEach(function (p) {
+      Object.keys(p).forEach(function (f) {
+        if (typeof p[f] !== "undefined") props[f] = p[f]
+      })
+    })
+
+    // no nulls allowed in path or linkpath
+    ;["path", "linkpath"].forEach(function (p) {
+      if (props.hasOwnProperty(p)) {
+        props[p] = props[p].split("\0")[0]
+      }
+    })
+
+
+    // set date fields to be a proper date
+    ;["mtime", "ctime", "atime"].forEach(function (p) {
+      if (props.hasOwnProperty(p)) {
+        props[p] = new Date(props[p] * 1000)
+      }
+    })
+
+    // set the type so that we know what kind of file to create
+    var type
+    switch (tar.types[props.type]) {
+      case "OldFile":
+      case "ContiguousFile":
+        type = "File"
+        break
+
+      case "GNUDumpDir":
+        type = "Directory"
+        break
+
+      case undefined:
+        type = "Unknown"
+        break
+
+      case "Link":
+      case "SymbolicLink":
+      case "CharacterDevice":
+      case "BlockDevice":
+      case "Directory":
+      case "FIFO":
+      default:
+        type = tar.types[props.type]
+    }
+
+    this.type = type
+    this.path = props.path
+    this.size = props.size
+
+    // size is special, since it signals when the file needs to end.
+    this._remaining = props.size
+  }
+, warn: fstream.warn
+, error: fstream.error
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header-writer.js	(revision 533)
@@ -0,0 +1,192 @@
+
+module.exports = ExtendedHeaderWriter
+
+var inherits = require("../vendor/inherits/inherits.js")
+  , EntryWriter = require("./entry-writer.js")
+
+inherits(ExtendedHeaderWriter, EntryWriter)
+
+var tar = require("../tar.js")
+  , path = require("path")
+  , inherits = require("../vendor/inherits/inherits.js")
+  , TarHeader = require("./header.js")
+
+// props is the props of the thing we need to write an
+// extended header for.
+// Don't be shy with it.  Just encode everything.
+function ExtendedHeaderWriter (props) {
+  // console.error(">> ehw ctor")
+  var me = this
+
+  if (!(me instanceof ExtendedHeaderWriter)) {
+    return new ExtendedHeaderWriter(props)
+  }
+
+  me.fields = props
+
+  var p =
+    { path : ("PaxHeader" + path.join("/", props.path || ""))
+             .replace(/\\/g, "/").substr(0, 100)
+    , mode : props.mode || 0666
+    , uid : props.uid || 0
+    , gid : props.gid || 0
+    , size : 0 // will be set later
+    , mtime : props.mtime || Date.now() / 1000
+    , type : "x"
+    , linkpath : ""
+    , ustar : "ustar\0"
+    , ustarver : "00"
+    , uname : props.uname || ""
+    , gname : props.gname || ""
+    , devmaj : props.devmaj || 0
+    , devmin : props.devmin || 0
+    }
+
+
+  EntryWriter.call(me, p)
+  // console.error(">> ehw props", me.props)
+  me.props = p
+
+  me._meta = true
+}
+
+ExtendedHeaderWriter.prototype.end = function () {
+  // console.error(">> ehw end")
+  var me = this
+
+  if (me._ended) return
+  me._ended = true
+
+  me._encodeFields()
+
+  if (me.props.size === 0) {
+    // nothing to write!
+    me._ready = true
+    me._stream.end()
+    return
+  }
+
+  me._stream.write(TarHeader.encode(me.props))
+  me.body.forEach(function (l) {
+    me._stream.write(l)
+  })
+  me._ready = true
+
+  // console.error(">> ehw _process calling end()", me.props)
+  this._stream.end()
+}
+
+ExtendedHeaderWriter.prototype._encodeFields = function () {
+  // console.error(">> ehw _encodeFields")
+  this.body = []
+  if (this.fields.prefix) {
+    this.fields.path = this.fields.prefix + "/" + this.fields.path
+    this.fields.prefix = ""
+  }
+  encodeFields(this.fields, "", this.body, this.fields.noProprietary)
+  var me = this
+  this.body.forEach(function (l) {
+    me.props.size += l.length
+  })
+}
+
+function encodeFields (fields, prefix, body, nop) {
+  // console.error(">> >> ehw encodeFields")
+  // "%d %s=%s\n", <length>, <keyword>, <value>
+  // The length is a decimal number, and includes itself and the \n
+  // Numeric values are decimal strings.
+
+  Object.keys(fields).forEach(function (k) {
+    var val = fields[k]
+      , numeric = tar.numeric[k]
+
+    if (prefix) k = prefix + "." + k
+
+    // already including NODETAR.type, don't need File=true also
+    if (k === fields.type && val === true) return
+
+    switch (k) {
+      // don't include anything that's always handled just fine
+      // in the normal header, or only meaningful in the context
+      // of nodetar
+      case "mode":
+      case "cksum":
+      case "ustar":
+      case "ustarver":
+      case "prefix":
+      case "basename":
+      case "dirname":
+      case "needExtended":
+      case "block":
+      case "filter":
+        return
+
+      case "rdev":
+        if (val === 0) return
+        break
+
+      case "nlink":
+      case "dev": // Truly a hero among men, Creator of Star!
+      case "ino": // Speak his name with reverent awe!  It is:
+        k = "SCHILY." + k
+        break
+
+      default: break
+    }
+
+    if (val && typeof val === "object" &&
+        !Buffer.isBuffer(val)) encodeFields(val, k, body, nop)
+    else if (val === null || val === undefined) return
+    else body.push.apply(body, encodeField(k, val, nop))
+  })
+
+  return body
+}
+
+function encodeField (k, v, nop) {
+  // lowercase keys must be valid, otherwise prefix with
+  // "NODETAR."
+  if (k.charAt(0) === k.charAt(0).toLowerCase()) {
+    var m = k.split(".")[0]
+    if (!tar.knownExtended[m]) k = "NODETAR." + k
+  }
+
+  // no proprietary
+  if (nop && k.charAt(0) !== k.charAt(0).toLowerCase()) {
+    return []
+  }
+
+  if (typeof val === "number") val = val.toString(10)
+
+  var s = new Buffer(" " + k + "=" + v + "\n")
+    , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1
+
+  // console.error("1 s=%j digits=%j s.length=%d", s.toString(), digits, s.length)
+
+  // if adding that many digits will make it go over that length,
+  // then add one to it. For example, if the string is:
+  // " foo=bar\n"
+  // then that's 9 characters.  With the "9", that bumps the length
+  // up to 10.  However, this is invalid:
+  // "10 foo=bar\n"
+  // but, since that's actually 11 characters, since 10 adds another
+  // character to the length, and the length includes the number
+  // itself.  In that case, just bump it up again.
+  if (s.length + digits >= Math.pow(10, digits)) digits += 1
+  // console.error("2 s=%j digits=%j s.length=%d", s.toString(), digits, s.length)
+
+  var len = digits + s.length
+  // console.error("3 s=%j digits=%j s.length=%d len=%d", s.toString(), digits, s.length, len)
+  var lenBuf = new Buffer("" + len)
+  if (lenBuf.length + s.length !== len) {
+    throw new Error("Bad length calculation\n"+
+                    "len="+len+"\n"+
+                    "lenBuf="+JSON.stringify(lenBuf.toString())+"\n"+
+                    "lenBuf.length="+lenBuf.length+"\n"+
+                    "digits="+digits+"\n"+
+                    "s="+JSON.stringify(s.toString())+"\n"+
+                    "s.length="+s.length)
+  }
+
+  return [lenBuf, s]
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header.js	(revision 533)
@@ -0,0 +1,139 @@
+// An Entry consisting of:
+//
+// "%d %s=%s\n", <length>, <keyword>, <value>
+//
+// The length is a decimal number, and includes itself and the \n
+// \0 does not terminate anything.  Only the length terminates the string.
+// Numeric values are decimal strings.
+
+module.exports = ExtendedHeader
+
+var Entry = require("./entry.js")
+  , inherits = require("../vendor/inherits/inherits.js")
+  , tar = require("../tar.js")
+  , numeric = tar.numeric
+  , keyTrans = { "SCHILY.dev": "dev"
+               , "SCHILY.ino": "ino"
+               , "SCHILY.nlink": "nlink" }
+
+function ExtendedHeader () {
+  Entry.apply(this, arguments)
+  this.on("data", this._parse)
+  this.fields = {}
+  this._position = 0
+  this._fieldPos = 0
+  this._state = SIZE
+  this._sizeBuf = []
+  this._keyBuf = []
+  this._valBuf = []
+  this._size = -1
+  this._key = ""
+}
+
+inherits(ExtendedHeader, Entry, { _parse: parse })
+
+var s = 0
+  , states = ExtendedHeader.states = {}
+  , SIZE = states.SIZE = s++
+  , KEY  = states.KEY  = s++
+  , VAL  = states.VAL  = s++
+  , ERR  = states.ERR  = s++
+
+Object.keys(states).forEach(function (s) {
+  states[states[s]] = states[s]
+})
+
+states[s] = null
+
+// char code values for comparison
+var _0 = "0".charCodeAt(0)
+  , _9 = "9".charCodeAt(0)
+  , point = ".".charCodeAt(0)
+  , a = "a".charCodeAt(0)
+  , Z = "Z".charCodeAt(0)
+  , a = "a".charCodeAt(0)
+  , z = "z".charCodeAt(0)
+  , space = " ".charCodeAt(0)
+  , eq = "=".charCodeAt(0)
+  , cr = "\n".charCodeAt(0)
+
+function parse (c) {
+  if (this._state === ERR) return
+
+  for ( var i = 0, l = c.length
+      ; i < l
+      ; this._position++, this._fieldPos++, i++) {
+    // console.error("top of loop, size="+this._size)
+
+    var b = c[i]
+
+    if (this._size >= 0 && this._fieldPos > this._size) {
+      error(this, "field exceeds length="+this._size)
+      return
+    }
+
+    switch (this._state) {
+      case ERR: return
+
+      case SIZE:
+        // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString())
+        if (b === space) {
+          this._state = KEY
+          // this._fieldPos = this._sizeBuf.length
+          this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10)
+          this._sizeBuf.length = 0
+          continue
+        }
+        if (b < _0 || b > _9) {
+          error(this, "expected [" + _0 + ".." + _9 + "], got " + b)
+          return
+        }
+        this._sizeBuf.push(b)
+        continue
+
+      case KEY:
+        // can be any char except =, not > size.
+        if (b === eq) {
+          this._state = VAL
+          this._key = new Buffer(this._keyBuf).toString()
+          if (keyTrans[this._key]) this._key = keyTrans[this._key]
+          this._keyBuf.length = 0
+          continue
+        }
+        this._keyBuf.push(b)
+        continue
+
+      case VAL:
+        // field must end with cr
+        if (this._fieldPos === this._size - 1) {
+          // console.error("finished with "+this._key)
+          if (b !== cr) {
+            error(this, "expected \\n at end of field")
+            return
+          }
+          var val = new Buffer(this._valBuf).toString()
+          if (numeric[this._key]) {
+            val = parseFloat(val)
+          }
+          this.fields[this._key] = val
+
+          this._valBuf.length = 0
+          this._state = SIZE
+          this._size = -1
+          this._fieldPos = -1
+          continue
+        }
+        this._valBuf.push(b)
+        continue
+    }
+  }
+}
+
+function error (me, msg) {
+  msg = "invalid header: " + msg
+      + "\nposition=" + me._position
+      + "\nfield position=" + me._fieldPos
+
+  me.error(msg)
+  me.state = ERR
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extract.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extract.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extract.js	(revision 533)
@@ -0,0 +1,78 @@
+// give it a tarball and a path, and it'll dump the contents
+
+module.exports = Extract
+
+var tar = require("../tar.js")
+  , fstream = require("../vendor/fstream/fstream.js")
+  , inherits = require("../vendor/inherits/inherits.js")
+  , path = require("path")
+
+function Extract (opts) {
+  if (!(this instanceof Extract)) return new Extract(opts)
+  tar.Parse.apply(this)
+
+  // have to dump into a directory
+  opts.type = "Directory"
+  opts.Directory = true
+
+  if (typeof opts !== "object") {
+    opts = { path: opts }
+  }
+
+  // better to drop in cwd? seems more standard.
+  opts.path = opts.path || path.resolve("node-tar-extract")
+  opts.type = "Directory"
+  opts.Directory = true
+
+  // similar to --strip or --strip-components
+  opts.strip = +opts.strip
+  if (!opts.strip || opts.strip <= 0) opts.strip = 0
+
+  this._fst = fstream.Writer(opts)
+
+  this.pause()
+  var me = this
+
+  // Hardlinks in tarballs are relative to the root
+  // of the tarball.  So, they need to be resolved against
+  // the target directory in order to be created properly.
+  me.on("entry", function (entry) {
+    // if there's a "strip" argument, then strip off that many
+    // path components.
+    if (opts.strip) {
+      var p = entry.path.split("/").slice(opts.strip).join("/")
+      entry.path = entry.props.path = p
+      if (entry.linkpath) {
+        var lp = entry.linkpath.split("/").slice(opts.strip).join("/")
+        entry.linkpath = entry.props.linkpath = lp
+      }
+    }
+    if (entry.type !== "Link") return
+    entry.linkpath = entry.props.linkpath =
+      path.join(opts.path, path.join("/", entry.props.linkpath))
+  })
+
+  this._fst.on("ready", function () {
+    me.pipe(me._fst, { end: false })
+    me.resume()
+  })
+
+  // this._fst.on("end", function () {
+  //   console.error("\nEEEE Extract End", me._fst.path)
+  // })
+
+  this._fst.on("close", function () {
+    // console.error("\nEEEE Extract End", me._fst.path)
+    me.emit("end")
+    me.emit("close")
+  })
+}
+
+inherits(Extract, tar.Parse)
+
+Extract.prototype._streamEnd = function () {
+  var me = this
+  if (!me._ended) me.error("unexpected eof")
+  me._fst.end()
+  // my .end() is coming later.
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/global-header-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/global-header-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/global-header-writer.js	(revision 533)
@@ -0,0 +1,14 @@
+module.exports = GlobalHeaderWriter
+
+var ExtendedHeaderWriter = require("./extended-header-writer.js")
+  , inherits = require("../vendor/inherits/inherits.js")
+
+inherits(GlobalHeaderWriter, ExtendedHeaderWriter)
+
+function GlobalHeaderWriter (props) {
+  if (!(this instanceof GlobalHeaderWriter)) {
+    return new GlobalHeaderWriter(props)
+  }
+  ExtendedHeaderWriter.call(this, props)
+  this.props.type = "g"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/header.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/header.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/header.js	(revision 533)
@@ -0,0 +1,385 @@
+// parse a 512-byte header block to a data object, or vice-versa
+// If the data won't fit nicely in a simple header, then generate
+// the appropriate extended header file, and return that.
+
+module.exports = TarHeader
+
+var tar = require("../tar.js")
+  , fields = tar.fields
+  , fieldOffs = tar.fieldOffs
+  , fieldEnds = tar.fieldEnds
+  , fieldSize = tar.fieldSize
+  , numeric = tar.numeric
+  , assert = require("assert").ok
+  , space = " ".charCodeAt(0)
+  , slash = "/".charCodeAt(0)
+  , bslash = process.platform === "win32" ? "\\".charCodeAt(0) : null
+
+function TarHeader (block) {
+  if (!(this instanceof TarHeader)) return new TarHeader(block)
+  if (block) this.decode(block)
+}
+
+TarHeader.prototype =
+  { decode : decode
+  , encode: encode
+  , calcSum: calcSum
+  , checkSum: checkSum
+  }
+
+TarHeader.parseNumeric = parseNumeric
+TarHeader.encode = encode
+TarHeader.decode = decode
+
+// note that this will only do the normal ustar header, not any kind
+// of extended posix header file.  If something doesn't fit comfortably,
+// then it will set obj.needExtended = true, and set the block to
+// the closest approximation.
+function encode (obj) {
+  if (!obj && !(this instanceof TarHeader)) throw new Error(
+    "encode must be called on a TarHeader, or supplied an object")
+
+  obj = obj || this
+  var block = obj.block = new Buffer(512)
+
+  // if the object has a "prefix", then that's actually an extension of
+  // the path field.
+  if (obj.prefix) {
+    // console.error("%% header encoding, got a prefix", obj.prefix)
+    obj.path = obj.prefix + "/" + obj.path
+    // console.error("%% header encoding, prefixed path", obj.path)
+    obj.prefix = ""
+  }
+
+  obj.needExtended = false
+
+  if (obj.mode) {
+    if (typeof obj.mode === "string") obj.mode = parseInt(obj.mode, 8)
+    obj.mode = obj.mode & 0777
+  }
+
+  for (var f = 0; fields[f] !== null; f ++) {
+    var field = fields[f]
+      , off = fieldOffs[f]
+      , end = fieldEnds[f]
+      , ret
+
+    switch (field) {
+      case "cksum":
+        // special, done below, after all the others
+        break
+
+      case "prefix":
+        // special, this is an extension of the "path" field.
+        // console.error("%% header encoding, skip prefix later")
+        break
+
+      case "type":
+        // convert from long name to a single char.
+        var type = obj.type || "0"
+        if (type.length > 1) {
+          type = tar.types[obj.type]
+          if (!type) type = "0"
+        }
+        writeText(block, off, end, type)
+        break
+
+      case "path":
+        // uses the "prefix" field if > 100 bytes, but <= 255
+        var pathLen = Buffer.byteLength(obj.path)
+          , pathFSize = fieldSize[fields.path]
+          , prefFSize = fieldSize[fields.prefix]
+
+        // paths between 100 and 255 should use the prefix field.
+        // longer than 255
+        if (pathLen > pathFSize &&
+            pathLen <= pathFSize + prefFSize) {
+          // need to find a slash somewhere in the middle so that
+          // path and prefix both fit in their respective fields
+          var searchStart = pathLen - 1 - pathFSize
+            , searchEnd = prefFSize
+            , found = false
+            , pathBuf = new Buffer(obj.path)
+
+          for ( var s = searchStart
+              ; (s <= searchEnd)
+              ; s ++ ) {
+            if (pathBuf[s] === slash || pathBuf[s] === bslash) {
+              found = s
+              break
+            }
+          }
+
+          if (found !== false) {
+            prefix = pathBuf.slice(0, found).toString("utf8")
+            path = pathBuf.slice(found + 1).toString("utf8")
+
+            ret = writeText(block, off, end, path)
+            off = fieldOffs[fields.prefix]
+            end = fieldEnds[fields.prefix]
+            // console.error("%% header writing prefix", off, end, prefix)
+            ret = writeText(block, off, end, prefix) || ret
+            break
+          }
+        }
+
+        // paths less than 100 chars don't need a prefix
+        // and paths longer than 255 need an extended header and will fail
+        // on old implementations no matter what we do here.
+        // Null out the prefix, and fallthrough to default.
+        // console.error("%% header writing no prefix")
+        var poff = fieldOffs[fields.prefix]
+          , pend = fieldEnds[fields.prefix]
+        writeText(block, poff, pend, "")
+        // fallthrough
+
+      // all other fields are numeric or text
+      default:
+        ret = numeric[field]
+            ? writeNumeric(block, off, end, obj[field])
+            : writeText(block, off, end, obj[field] || "")
+        break
+    }
+    obj.needExtended = obj.needExtended || ret
+  }
+
+  var off = fieldOffs[fields.cksum]
+    , end = fieldEnds[fields.cksum]
+
+  writeNumeric(block, off, end, calcSum.call(this, block))
+
+  return block
+}
+
+// if it's a negative number, or greater than will fit,
+// then use write256.
+var MAXNUM = { 12: 077777777777
+             , 11: 07777777777
+             , 8 : 07777777
+             , 7 : 0777777 }
+function writeNumeric (block, off, end, num) {
+  var writeLen = end - off
+    , maxNum = MAXNUM[writeLen] || 0
+
+  num = num || 0
+  // console.error("  numeric", num)
+
+  if (num instanceof Date ||
+      Object.prototype.toString.call(num) === "[object Date]") {
+    num = num.getTime() / 1000
+  }
+
+  if (num > maxNum || num < 0) {
+    write256(block, off, end, num)
+    // need an extended header if negative or too big.
+    return true
+  }
+
+  // god, tar is so annoying
+  // if the string is small enough, you should put a space
+  // between the octal string and the \0, but if it doesn't
+  // fit, then don't.
+  var numStr = Math.floor(num).toString(8)
+  if (num < MAXNUM[writeLen - 1]) numStr += " "
+
+  // pad with "0" chars
+  if (numStr.length < writeLen) {
+    numStr = (new Array(writeLen - numStr.length).join("0")) + numStr
+  }
+
+  if (numStr.length !== writeLen - 1) {
+    throw new Error("invalid length: " + JSON.stringify(numStr) + "\n" +
+                    "expected: "+writeLen)
+  }
+  block.write(numStr, off, writeLen, "utf8")
+  block[end - 1] = 0
+}
+
+function write256 (block, off, end, num) {
+  var buf = block.slice(off, end)
+  var positive = num >= 0
+  buf[0] = positive ? 0x80 : 0xFF
+
+  // get the number as a base-256 tuple
+  if (!positive) num *= -1
+  var tuple = []
+  do {
+    var n = num % 256
+    tuple.push(n)
+    num = (num - n) / 256
+  } while (num)
+
+  var bytes = tuple.length
+
+  var fill = buf.length - bytes
+  for (var i = 1; i < fill; i ++) {
+    buf[i] = positive ? 0 : 0xFF
+  }
+
+  // tuple is a base256 number, with [0] as the *least* significant byte
+  // if it's negative, then we need to flip all the bits once we hit the
+  // first non-zero bit.  The 2's-complement is (0x100 - n), and the 1's-
+  // complement is (0xFF - n).
+  var zero = true
+  for (i = bytes; i > 0; i --) {
+    var byte = tuple[bytes - i]
+    if (positive) buf[fill + i] = byte
+    else if (zero && byte === 0) buf[fill + i] = 0
+    else if (zero) {
+      zero = false
+      buf[fill + i] = 0x100 - byte
+    } else buf[fill + i] = 0xFF - byte
+  }
+}
+
+function writeText (block, off, end, str) {
+  // strings are written as utf8, then padded with \0
+  var strLen = Buffer.byteLength(str)
+    , writeLen = Math.min(strLen, end - off)
+    // non-ascii fields need extended headers
+    // long fields get truncated
+    , needExtended = strLen !== str.length || strLen > writeLen
+
+  // write the string, and null-pad
+  if (writeLen > 0) block.write(str, off, writeLen, "utf8")
+  for (var i = off + writeLen; i < end; i ++) block[i] = 0
+
+  return needExtended
+}
+
+function calcSum (block) {
+  block = block || this.block
+  assert(Buffer.isBuffer(block) && block.length === 512)
+
+  if (!block) throw new Error("Need block to checksum")
+
+  // now figure out what it would be if the cksum was "        "
+  var sum = 0
+    , start = fieldOffs[fields.cksum]
+    , end = fieldEnds[fields.cksum]
+
+  for (var i = 0; i < fieldOffs[fields.cksum]; i ++) {
+    sum += block[i]
+  }
+
+  for (var i = start; i < end; i ++) {
+    sum += space
+  }
+
+  for (var i = end; i < 512; i ++) {
+    sum += block[i]
+  }
+
+  return sum
+}
+
+
+function checkSum (block) {
+  var sum = calcSum.call(this, block)
+  block = block || this.block
+
+  var cksum = block.slice(fieldOffs[fields.cksum], fieldEnds[fields.cksum])
+  cksum = parseNumeric(cksum)
+
+  return cksum === sum
+}
+
+function decode (block) {
+  block = block || this.block
+  assert(Buffer.isBuffer(block) && block.length === 512)
+
+  this.block = block
+  this.cksumValid = this.checkSum()
+
+  var prefix = null
+
+  // slice off each field.
+  for (var f = 0; fields[f] !== null; f ++) {
+    var field = fields[f]
+      , val = block.slice(fieldOffs[f], fieldEnds[f])
+
+    switch (field) {
+      case "ustar":
+        // if not ustar, then everything after that is just padding.
+        if (val.toString() !== "ustar\0") {
+          this.ustar = false
+          return
+        } else {
+          // console.error("ustar:", val, val.toString())
+          this.ustar = val.toString()
+        }
+        break
+
+      // prefix is special, since it might signal the xstar header
+      case "prefix":
+        var atime = parseNumeric(val.slice(131, 131 + 12))
+          , ctime = parseNumeric(val.slice(131 + 12, 131 + 12 + 12))
+        if ((val[130] === 0 || val[130] === space) &&
+            typeof atime === "number" &&
+            typeof ctime === "number" &&
+            val[131 + 12] === space &&
+            val[131 + 12 + 12] === space) {
+          this.atime = atime
+          this.ctime = ctime
+          val = val.slice(0, 130)
+        }
+        prefix = val.toString("utf8").replace(/\0+$/, "")
+        // console.error("%% header reading prefix", prefix)
+        break
+
+      // all other fields are null-padding text
+      // or a number.
+      default:
+        if (numeric[field]) {
+          this[field] = parseNumeric(val)
+        } else {
+          this[field] = val.toString("utf8").replace(/\0+$/, "")
+        }
+        break
+    }
+  }
+
+  // if we got a prefix, then prepend it to the path.
+  if (prefix) {
+    this.path = prefix + "/" + this.path
+    // console.error("%% header got a prefix", this.path)
+  }
+}
+
+function parse256 (buf) {
+  // first byte MUST be either 80 or FF
+  // 80 for positive, FF for 2's comp
+  var positive
+  if (buf[0] === 0x80) positive = true
+  else if (buf[0] === 0xFF) positive = false
+  else return null
+
+  // build up a base-256 tuple from the least sig to the highest
+  var zero = false
+    , tuple = []
+  for (var i = buf.length - 1; i > 0; i --) {
+    var byte = buf[i]
+    if (positive) tuple.push(byte)
+    else if (zero && byte === 0) tuple.push(0)
+    else if (zero) {
+      zero = false
+      tuple.push(0x100 - byte)
+    } else tuple.push(0xFF - byte)
+  }
+
+  for (var sum = 0, i = 0, l = tuple.length; i < l; i ++) {
+    sum += tuple[i] * Math.pow(256, i)
+  }
+
+  return positive ? sum : -1 * sum
+}
+
+function parseNumeric (f) {
+  if (f[0] & 0x80) return parse256(f)
+
+  var str = f.toString("utf8").split("\0")[0].trim()
+    , res = parseInt(str, 8)
+
+  return isNaN(res) ? null : res
+}
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/pack.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/pack.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/pack.js	(revision 533)
@@ -0,0 +1,226 @@
+// pipe in an fstream, and it'll make a tarball.
+// key-value pair argument is global extended header props.
+
+module.exports = Pack
+
+var EntryWriter = require("./entry-writer.js")
+  , Stream = require("stream").Stream
+  , path = require("path")
+  , inherits = require("../vendor/inherits/inherits.js")
+  , GlobalHeaderWriter = require("./global-header-writer.js")
+  , collect = require("../vendor/fstream/fstream.js").collect
+  , eof = new Buffer(512)
+
+for (var i = 0; i < 512; i ++) eof[i] = 0
+
+inherits(Pack, Stream)
+
+function Pack (props) {
+  // console.error("-- p ctor")
+  var me = this
+  if (!(me instanceof Pack)) return new Pack(props)
+
+  if (props) me._noProprietary = props.noProprietary
+  else me._noProprietary = false
+
+  me._global = props
+
+  me.readable = true
+  me.writable = true
+  me._buffer = []
+  // console.error("-- -- set current to null in ctor")
+  me._currentEntry = null
+  me._processing = false
+
+  me._pipeRoot = null
+  me.on("pipe", function (src) {
+    if (src.root === me._pipeRoot) return
+    me._pipeRoot = src
+    src.on("end", function () {
+      me._pipeRoot = null
+    })
+    me.add(src)
+  })
+}
+
+Pack.prototype.addGlobal = function (props) {
+  // console.error("-- p addGlobal")
+  if (this._didGlobal) return
+  this._didGlobal = true
+
+  var me = this
+  GlobalHeaderWriter(props)
+    .on("data", function (c) {
+      me.emit("data", c)
+    })
+    .end()
+}
+
+Pack.prototype.add = function (stream) {
+  if (this._global && !this._didGlobal) this.addGlobal(this._global)
+
+  if (this._ended) return this.emit("error", new Error("add after end"))
+
+  collect(stream)
+  this._buffer.push(stream)
+  this._process()
+  this._needDrain = this._buffer.length > 0
+  return !this._needDrain
+}
+
+Pack.prototype.pause = function () {
+  this._paused = true
+  if (this._currentEntry) this._currentEntry.pause()
+  this.emit("pause")
+}
+
+Pack.prototype.resume = function () {
+  this._paused = false
+  if (this._currentEntry) this._currentEntry.resume()
+  this.emit("resume")
+  this._process()
+}
+
+Pack.prototype.end = function () {
+  this._ended = true
+  this._buffer.push(eof)
+  this._process()
+}
+
+Pack.prototype._process = function () {
+  var me = this
+  if (me._paused || me._processing) {
+    return
+  }
+
+  var entry = me._buffer.shift()
+
+  if (!entry) {
+    if (me._needDrain) {
+      me.emit("drain")
+    }
+    return
+  }
+
+  if (entry.ready === false) {
+    // console.error("-- entry is not ready", entry)
+    me._buffer.unshift(entry)
+    entry.on("ready", function () {
+      // console.error("-- -- ready!", entry)
+      me._process()
+    })
+    return
+  }
+
+  me._processing = true
+
+  if (entry === eof) {
+    // need 2 ending null blocks.
+    me.emit("data", eof)
+    me.emit("data", eof)
+    me.emit("end")
+    me.emit("close")
+    return
+  }
+
+  // Change the path to be relative to the root dir that was
+  // added to the tarball.
+  //
+  // XXX This should be more like how -C works, so you can
+  // explicitly set a root dir, and also explicitly set a pathname
+  // in the tarball to use.  That way we can skip a lot of extra
+  // work when resolving symlinks for bundled dependencies in npm.
+
+  var root = path.dirname((entry.root || entry).path)
+  var wprops = {}
+
+  Object.keys(entry.props).forEach(function (k) {
+    wprops[k] = entry.props[k]
+  })
+
+  if (me._noProprietary) wprops.noProprietary = true
+
+  wprops.path = path.relative(root, entry.path)
+
+  // actually not a matter of opinion or taste.
+  if (process.platform === "win32") {
+    wprops.path = wprops.path.replace(/\\/g, "/")
+  }
+
+  switch (wprops.type) {
+    // sockets not supported
+    case "Socket":
+      return
+
+    case "Directory":
+      wprops.path += "/"
+      wprops.size = 0
+      break
+    case "Link":
+      var lp = path.resolve(path.dirname(entry.path), entry.linkpath)
+      wprops.linkpath = path.relative(root, lp) || "."
+      wprops.size = 0
+      break
+    case "SymbolicLink":
+      var lp = path.resolve(path.dirname(entry.path), entry.linkpath)
+      wprops.linkpath = path.relative(path.dirname(entry.path), lp) || "."
+      wprops.size = 0
+      break
+  }
+
+  // console.error("-- new writer", wprops)
+  // if (!wprops.type) {
+  //   // console.error("-- no type?", entry.constructor.name, entry)
+  // }
+
+  // console.error("-- -- set current to new writer", wprops.path)
+  var writer = me._currentEntry = EntryWriter(wprops)
+
+  writer.parent = me
+
+  // writer.on("end", function () {
+  //   // console.error("-- -- writer end", writer.path)
+  // })
+
+  writer.on("data", function (c) {
+    me.emit("data", c)
+  })
+
+  writer.on("header", function () {
+    Buffer.prototype.toJSON = function () {
+      return this.toString().split(/\0/).join(".")
+    }
+    // console.error("-- -- writer header %j", writer.props)
+    if (writer.props.size === 0) nextEntry()
+  })
+  writer.on("close", nextEntry)
+
+  var ended = false
+  function nextEntry () {
+    if (ended) return
+    ended = true
+
+    // console.error("-- -- writer close", writer.path)
+    // console.error("-- -- set current to null", wprops.path)
+    me._currentEntry = null
+    me._processing = false
+    me._process()
+  }
+
+  writer.on("error", function (er) {
+    // console.error("-- -- writer error", writer.path)
+    me.emit("error", er)
+  })
+
+  // if it's the root, then there's no need to add its entries,
+  // or data, since they'll be added directly.
+  if (entry === me._pipeRoot) {
+    // console.error("-- is the root, don't auto-add")
+    writer.add = null
+  }
+
+  entry.pipe(writer)
+}
+
+Pack.prototype.destroy = function () {}
+Pack.prototype.write = function () {}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/parse.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/parse.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/parse.js	(revision 533)
@@ -0,0 +1,270 @@
+
+// A writable stream.
+// It emits "entry" events, which provide a readable stream that has
+// header info attached.
+
+module.exports = Parse.create = Parse
+
+var stream = require("stream")
+  , Stream = stream.Stream
+  , BlockStream = require("../vendor/block-stream/block-stream.js")
+  , tar = require("../tar.js")
+  , TarHeader = require("./header.js")
+  , Entry = require("./entry.js")
+  , BufferEntry = require("./buffer-entry.js")
+  , ExtendedHeader = require("./extended-header.js")
+  , assert = require("assert").ok
+  , inherits = require("../vendor/inherits/inherits.js")
+  , fstream = require("../vendor/fstream/fstream.js")
+
+// reading a tar is a lot like reading a directory
+// However, we're actually not going to run the ctor,
+// since it does a stat and various other stuff.
+// This inheritance gives us the pause/resume/pipe
+// behavior that is desired.
+inherits(Parse, fstream.Reader)
+
+function Parse () {
+  var me = this
+  if (!(me instanceof Parse)) return new Parse()
+
+  // doesn't apply fstream.Reader ctor?
+  // no, becasue we don't want to stat/etc, we just
+  // want to get the entry/add logic from .pipe()
+  Stream.apply(me)
+
+  me.writable = true
+  me.readable = true
+  me._stream = new BlockStream(512)
+  me.position = 0
+
+  me._stream.on("error", function (e) {
+    me.emit("error", e)
+  })
+
+  me._stream.on("data", function (c) {
+    me._process(c)
+  })
+
+  me._stream.on("end", function () {
+    me._streamEnd()
+  })
+
+  me._stream.on("drain", function () {
+    me.emit("drain")
+  })
+}
+
+// overridden in Extract class, since it needs to
+// wait for its DirWriter part to finish before
+// emitting "end"
+Parse.prototype._streamEnd = function () {
+  var me = this
+  if (!me._ended) me.error("unexpected eof")
+  me.emit("end")
+}
+
+// a tar reader is actually a filter, not just a readable stream.
+// So, you should pipe a tarball stream into it, and it needs these
+// write/end methods to do that.
+Parse.prototype.write = function (c) {
+  if (this._ended) {
+    // gnutar puts a LOT of nulls at the end.
+    // you can keep writing these things forever.
+    // Just ignore them.
+    for (var i = 0, l = c.length; i > l; i ++) {
+      if (c[i] !== 0) return this.error("write() after end()")
+    }
+    return
+  }
+  return this._stream.write(c)
+}
+
+Parse.prototype.end = function (c) {
+  this._ended = true
+  return this._stream.end(c)
+}
+
+// don't need to do anything, since we're just
+// proxying the data up from the _stream.
+// Just need to override the parent's "Not Implemented"
+// error-thrower.
+Parse.prototype._read = function () {}
+
+Parse.prototype._process = function (c) {
+  assert(c && c.length === 512, "block size should be 512")
+
+  // one of three cases.
+  // 1. A new header
+  // 2. A part of a file/extended header
+  // 3. One of two or more EOF null blocks
+
+  if (this._entry) {
+    var entry = this._entry
+    entry.write(c)
+    if (entry._remaining === 0) {
+      entry.end()
+      this._entry = null
+    }
+  } else {
+    // either zeroes or a header
+    var zero = true
+    for (var i = 0; i < 512 && zero; i ++) {
+      zero = c[i] === 0
+    }
+
+    // eof is *at least* 2 blocks of nulls, and then the end of the
+    // file.  you can put blocks of nulls between entries anywhere,
+    // so appending one tarball to another is technically valid.
+    // ending without the eof null blocks is not allowed, however.
+    if (zero) {
+      this._ended = this._eofStarted
+      this._eofStarted = true
+    } else {
+      this._ended = this._eofStarted = false
+      this._startEntry(c)
+    }
+
+  }
+
+  this.position += 512
+}
+
+// take a header chunk, start the right kind of entry.
+Parse.prototype._startEntry = function (c) {
+  var header = new TarHeader(c)
+    , self = this
+    , entry
+    , ev
+    , EntryType
+    , onend
+    , meta = false
+
+  if (null === header.size || !header.cksumValid) {
+    var e = new Error("invalid tar file")
+    e.header = header
+    e.tar_file_offset = this.position
+    e.tar_block = this.position / 512
+    this.emit("error", e)
+  }
+
+  switch (tar.types[header.type]) {
+    case "File":
+    case "OldFile":
+    case "Link":
+    case "SymbolicLink":
+    case "CharacterDevice":
+    case "BlockDevice":
+    case "Directory":
+    case "FIFO":
+    case "ContiguousFile":
+    case "GNUDumpDir":
+      // start a file.
+      // pass in any extended headers
+      // These ones consumers are typically most interested in.
+      EntryType = Entry
+      ev = "entry"
+      break
+
+    case "GlobalExtendedHeader":
+      // extended headers that apply to the rest of the tarball
+      EntryType = ExtendedHeader
+      onend = function () {
+        self._global = self._global || {}
+        Object.keys(entry.fields).forEach(function (k) {
+          self._global[k] = entry.fields[k]
+        })
+      }
+      ev = "globalExtendedHeader"
+      meta = true
+      break
+
+    case "ExtendedHeader":
+    case "OldExtendedHeader":
+      // extended headers that apply to the next entry
+      EntryType = ExtendedHeader
+      onend = function () {
+        self._extended = entry.fields
+      }
+      ev = "extendedHeader"
+      meta = true
+      break
+
+    case "NextFileHasLongLinkpath":
+      // set linkpath=<contents> in extended header
+      EntryType = BufferEntry
+      onend = function () {
+        self._extended = self._extended || {}
+        self._extended.linkpath = entry.body
+      }
+      ev = "longLinkpath"
+      meta = true
+      break
+
+    case "NextFileHasLongPath":
+    case "OldGnuLongPath":
+      // set path=<contents> in file-extended header
+      EntryType = BufferEntry
+      onend = function () {
+        self._extended = self._extended || {}
+        self._extended.path = entry.body
+      }
+      ev = "longPath"
+      meta = true
+      break
+
+    default:
+      // all the rest we skip, but still set the _entry
+      // member, so that we can skip over their data appropriately.
+      // emit an event to say that this is an ignored entry type?
+      EntryType = Entry
+      ev = "ignoredEntry"
+      break
+  }
+
+  var global, extended
+  if (meta) {
+    global = extended = null
+  } else {
+    var global = this._global
+    var extended = this._extended
+
+    // extendedHeader only applies to one entry, so once we start
+    // an entry, it's over.
+    this._extended = null
+  }
+  entry = new EntryType(header, extended, global)
+  entry.meta = meta
+
+  // only proxy data events of normal files.
+  if (!meta) {
+    entry.on("data", function (c) {
+      me.emit("data", c)
+    })
+  }
+
+  if (onend) entry.on("end", onend)
+
+  this._entry = entry
+  var me = this
+
+  entry.on("pause", function () {
+    me.pause()
+  })
+
+  entry.on("resume", function () {
+    me.resume()
+  })
+
+  if (this.listeners("*").length) {
+    this.emit("*", ev, entry)
+  }
+
+  this.emit(ev, entry)
+
+  // Zero-byte entry.  End immediately.
+  if (entry.props.size === 0) {
+    entry.end()
+    this._entry = null
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/tar.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/tar.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/tar.js	(revision 533)
@@ -0,0 +1,172 @@
+// field paths that every tar file must have.
+// header is padded to 512 bytes.
+var f = 0
+  , fields = {}
+  , path = fields.path = f++
+  , mode = fields.mode = f++
+  , uid = fields.uid = f++
+  , gid = fields.gid = f++
+  , size = fields.size = f++
+  , mtime = fields.mtime = f++
+  , cksum = fields.cksum = f++
+  , type = fields.type = f++
+  , linkpath = fields.linkpath = f++
+  , headerSize = 512
+  , blockSize = 512
+  , fieldSize = []
+
+fieldSize[path] = 100
+fieldSize[mode] = 8
+fieldSize[uid] = 8
+fieldSize[gid] = 8
+fieldSize[size] = 12
+fieldSize[mtime] = 12
+fieldSize[cksum] = 8
+fieldSize[type] = 1
+fieldSize[linkpath] = 100
+
+// "ustar\0" may introduce another bunch of headers.
+// these are optional, and will be nulled out if not present.
+
+var ustar = fields.ustar = f++
+  , ustarver = fields.ustarver = f++
+  , uname = fields.uname = f++
+  , gname = fields.gname = f++
+  , devmaj = fields.devmaj = f++
+  , devmin = fields.devmin = f++
+  , prefix = fields.prefix = f++
+  , fill = fields.fill = f++
+
+// terminate fields.
+fields[f] = null
+
+fieldSize[ustar] = 6
+fieldSize[ustarver] = 2
+fieldSize[uname] = 32
+fieldSize[gname] = 32
+fieldSize[devmaj] = 8
+fieldSize[devmin] = 8
+fieldSize[prefix] = 155
+fieldSize[fill] = 12
+
+// nb: prefix field may in fact be 130 bytes of prefix,
+// a null char, 12 bytes for atime, 12 bytes for ctime.
+//
+// To recognize this format:
+// 1. prefix[130] === ' ' or '\0'
+// 2. atime and ctime are octal numeric values
+// 3. atime and ctime have ' ' in their last byte
+
+var fieldEnds = {}
+  , fieldOffs = {}
+  , fe = 0
+for (var i = 0; i < f; i ++) {
+  fieldOffs[i] = fe
+  fieldEnds[i] = (fe += fieldSize[i])
+}
+
+// build a translation table of field paths.
+Object.keys(fields).forEach(function (f) {
+  if (fields[f] !== null) fields[fields[f]] = f
+})
+
+// different values of the 'type' field
+// paths match the values of Stats.isX() functions, where appropriate
+var types =
+  { 0: "File"
+  , "\0": "OldFile" // like 0
+  , 1: "Link"
+  , 2: "SymbolicLink"
+  , 3: "CharacterDevice"
+  , 4: "BlockDevice"
+  , 5: "Directory"
+  , 6: "FIFO"
+  , 7: "ContiguousFile" // like 0
+  // posix headers
+  , g: "GlobalExtendedHeader" // k=v for the rest of the archive
+  , x: "ExtendedHeader" // k=v for the next file
+  // vendor-specific stuff
+  , A: "SolarisACL" // skip
+  , D: "GNUDumpDir" // like 5, but with data, which should be skipped
+  , I: "Inode" // metadata only, skip
+  , K: "NextFileHasLongLinkpath" // data = link path of next file
+  , L: "NextFileHasLongPath" // data = path of next file
+  , M: "ContinuationFile" // skip
+  , N: "OldGnuLongPath" // like L
+  , S: "SparseFile" // skip
+  , V: "TapeVolumeHeader" // skip
+  , X: "OldExtendedHeader" // like x
+  }
+
+Object.keys(types).forEach(function (t) {
+  types[types[t]] = types[types[t]] || t
+})
+
+// values for the mode field
+var modes =
+  { suid: 04000 // set uid on extraction
+  , sgid: 02000 // set gid on extraction
+  , svtx: 01000 // set restricted deletion flag on dirs on extraction
+  , uread:  0400
+  , uwrite: 0200
+  , uexec:  0100
+  , gread:  040
+  , gwrite: 020
+  , gexec:  010
+  , oread:  4
+  , owrite: 2
+  , oexec:  1
+  , all: 07777
+  }
+
+var numeric =
+  { mode: true
+  , uid: true
+  , gid: true
+  , size: true
+  , mtime: true
+  , devmaj: true
+  , devmin: true
+  , cksum: true
+  , atime: true
+  , ctime: true
+  , dev: true
+  , ino: true
+  , nlink: true
+  }
+
+Object.keys(modes).forEach(function (t) {
+  modes[modes[t]] = modes[modes[t]] || t
+})
+
+var knownExtended =
+  { atime: true
+  , charset: true
+  , comment: true
+  , ctime: true
+  , gid: true
+  , gname: true
+  , linkpath: true
+  , mtime: true
+  , path: true
+  , realtime: true
+  , security: true
+  , size: true
+  , uid: true
+  , uname: true }
+
+
+exports.fields = fields
+exports.fieldSize = fieldSize
+exports.fieldOffs = fieldOffs
+exports.fieldEnds = fieldEnds
+exports.types = types
+exports.modes = modes
+exports.numeric = numeric
+exports.headerSize = headerSize
+exports.blockSize = blockSize
+exports.knownExtended = knownExtended
+
+exports.Pack = require("./lib/pack.js")
+exports.Parse = require("./lib/parse.js")
+exports.Extract = require("./lib/extract.js")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/LICENCE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/LICENCE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/LICENCE	(revision 533)
@@ -0,0 +1,25 @@
+Copyright (c) Isaac Z. Schlueter
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/README.md	(revision 533)
@@ -0,0 +1,14 @@
+# block-stream
+
+A stream of blocks.
+
+Write data into it, and it'll output data in buffer blocks the size you
+specify, padding with zeroes if necessary.
+
+```javascript
+var block = new BlockStream(512)
+fs.createReadStream("some-file").pipe(block)
+block.pipe(fs.createWriteStream("block-file"))
+```
+
+When `.end()` or `.flush()` is called, it'll pad the block with zeroes.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/block-stream.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/block-stream.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/block-stream.js	(revision 533)
@@ -0,0 +1,209 @@
+// write data to it, and it'll emit data in 512 byte blocks.
+// if you .end() or .flush(), it'll emit whatever it's got,
+// padded with nulls to 512 bytes.
+
+module.exports = BlockStream
+
+var Stream = require("stream").Stream
+  , inherits = require("../inherits/inherits.js")
+  , assert = require("assert").ok
+  , debug = process.env.DEBUG ? console.error : function () {}
+
+function BlockStream (size, opt) {
+  this.writable = this.readable = true
+  this._opt = opt || {}
+  this._chunkSize = size || 512
+  this._offset = 0
+  this._buffer = []
+  this._bufferLength = 0
+  if (this._opt.nopad) this._zeroes = false
+  else {
+    this._zeroes = new Buffer(this._chunkSize)
+    for (var i = 0; i < this._chunkSize; i ++) {
+      this._zeroes[i] = 0
+    }
+  }
+}
+
+inherits(BlockStream, Stream)
+
+BlockStream.prototype.write = function (c) {
+  // debug("   BS write", c)
+  if (this._ended) throw new Error("BlockStream: write after end")
+  if (c && !Buffer.isBuffer(c)) c = new Buffer(c + "")
+  if (c.length) {
+    this._buffer.push(c)
+    this._bufferLength += c.length
+  }
+  // debug("pushed onto buffer", this._bufferLength)
+  if (this._bufferLength >= this._chunkSize) {
+    if (this._paused) {
+      // debug("   BS paused, return false, need drain")
+      this._needDrain = true
+      return false
+    }
+    this._emitChunk()
+  }
+  return true
+}
+
+BlockStream.prototype.pause = function () {
+  // debug("   BS pausing")
+  this._paused = true
+}
+
+BlockStream.prototype.resume = function () {
+  // debug("   BS resume")
+  this._paused = false
+  return this._emitChunk()
+}
+
+BlockStream.prototype.end = function (chunk) {
+  // debug("end", chunk)
+  if (typeof chunk === "function") cb = chunk, chunk = null
+  if (chunk) this.write(chunk)
+  this._ended = true
+  this.flush()
+}
+
+BlockStream.prototype.flush = function () {
+  this._emitChunk(true)
+}
+
+BlockStream.prototype._emitChunk = function (flush) {
+  // debug("emitChunk flush=%j emitting=%j paused=%j", flush, this._emitting, this._paused)
+
+  // emit a <chunkSize> chunk
+  if (flush && this._zeroes) {
+    // debug("    BS push zeroes", this._bufferLength)
+    // push a chunk of zeroes
+    var padBytes = (this._bufferLength % this._chunkSize)
+    if (padBytes !== 0) padBytes = this._chunkSize - padBytes
+    if (padBytes > 0) {
+      // debug("padBytes", padBytes, this._zeroes.slice(0, padBytes))
+      this._buffer.push(this._zeroes.slice(0, padBytes))
+      this._bufferLength += padBytes
+      // debug(this._buffer[this._buffer.length - 1].length, this._bufferLength)
+    }
+  }
+
+  if (this._emitting || this._paused) return
+  this._emitting = true
+
+  // debug("    BS entering loops")
+  var bufferIndex = 0
+  while (this._bufferLength >= this._chunkSize &&
+         (flush || !this._paused)) {
+    // debug("     BS data emission loop", this._bufferLength)
+
+    var out
+      , outOffset = 0
+      , outHas = this._chunkSize
+
+    while (outHas > 0 && (flush || !this._paused) ) {
+      // debug("    BS data inner emit loop", this._bufferLength)
+      var cur = this._buffer[bufferIndex]
+        , curHas = cur.length - this._offset
+      // debug("cur=", cur)
+      // debug("curHas=%j", curHas)
+      // If it's not big enough to fill the whole thing, then we'll need
+      // to copy multiple buffers into one.  However, if it is big enough,
+      // then just slice out the part we want, to save unnecessary copying.
+      // Also, need to copy if we've already done some copying, since buffers
+      // can't be joined like cons strings.
+      if (out || curHas < outHas) {
+        out = out || new Buffer(this._chunkSize)
+        cur.copy(out, outOffset,
+                 this._offset, this._offset + Math.min(curHas, outHas))
+      } else if (cur.length === outHas && this._offset === 0) {
+        // shortcut -- cur is exactly long enough, and no offset.
+        out = cur
+      } else {
+        // slice out the piece of cur that we need.
+        out = cur.slice(this._offset, this._offset + outHas)
+      }
+
+      if (curHas > outHas) {
+        // means that the current buffer couldn't be completely output
+        // update this._offset to reflect how much WAS written
+        this._offset += outHas
+        outHas = 0
+      } else {
+        // output the entire current chunk.
+        // toss it away
+        outHas -= curHas
+        outOffset += curHas
+        bufferIndex ++
+        this._offset = 0
+      }
+    }
+
+    this._bufferLength -= this._chunkSize
+    assert(out.length === this._chunkSize)
+    // debug("emitting data", out)
+    // debug("   BS emitting, paused=%j", this._paused, this._bufferLength)
+    this.emit("data", out)
+    out = null
+  }
+  // debug("    BS out of loops", this._bufferLength)
+
+  // whatever is left, it's not enough to fill up a block, or we're paused
+  this._buffer = this._buffer.slice(bufferIndex)
+  if (this._paused) {
+    // debug("    BS paused, leaving", this._bufferLength)
+    this._needsDrain = true
+    this._emitting = false
+    return
+  }
+
+  // if flushing, and not using null-padding, then need to emit the last
+  // chunk(s) sitting in the queue.  We know that it's not enough to
+  // fill up a whole block, because otherwise it would have been emitted
+  // above, but there may be some offset.
+  var l = this._buffer.length
+  if (flush && !this._zeroes && l) {
+    if (l === 1) {
+      if (this._offset) {
+        this.emit("data", this._buffer[0].slice(this._offset))
+      } else {
+        this.emit("data", this._buffer[0])
+      }
+    } else {
+      var outHas = this._bufferLength
+        , out = new Buffer(outHas)
+        , outOffset = 0
+      for (var i = 0; i < l; i ++) {
+        var cur = this._buffer[i]
+          , curHas = cur.length - this._offset
+        cur.copy(out, outOffset, this._offset)
+        this._offset = 0
+        outOffset += curHas
+        this._bufferLength -= curHas
+      }
+      this.emit("data", out)
+    }
+    // truncate
+    this._buffer.length = 0
+    this._bufferLength = 0
+    this._offset = 0
+  }
+
+  // now either drained or ended
+  // debug("either draining, or ended", this._bufferLength, this._ended)
+  // means that we've flushed out all that we can so far.
+  if (this._needDrain) {
+    // debug("emitting drain", this._bufferLength)
+    this._needDrain = false
+    this.emit("drain")
+  }
+
+  if ((this._bufferLength === 0) && this._ended && !this._endEmitted) {
+    // debug("emitting end", this._bufferLength)
+    this._endEmitted = true
+    this.emit("end")
+  }
+
+  this._emitting = false
+
+  // debug("    BS no longer emitting", flush, this._paused, this._emitting, this._bufferLength, this._chunkSize)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/LICENCE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/LICENCE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/LICENCE	(revision 533)
@@ -0,0 +1,25 @@
+Copyright (c) Isaac Z. Schlueter
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/README.md	(revision 533)
@@ -0,0 +1,76 @@
+Like FS streams, but with stat on them, and supporting directories and
+symbolic links, as well as normal files.  Also, you can use this to set
+the stats on a file, even if you don't change its contents, or to create
+a symlink, etc.
+
+So, for example, you can "write" a directory, and it'll call `mkdir`.  You
+can specify a uid and gid, and it'll call `chown`.  You can specify a
+`mtime` and `atime`, and it'll call `utimes`.  You can call it a symlink
+and provide a `linkpath` and it'll call `symlink`.
+
+Note that it won't automatically resolve symbolic links.  So, if you
+call `fstream.Reader('/some/symlink')` then you'll get an object
+that stats and then ends immediately (since it has no data).  To follow
+symbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:
+true })`.
+
+There are various checks to make sure that the bytes emitted are the
+same as the intended size, if the size is set.
+
+## Examples
+
+```javascript
+fstream
+  .Writer({ path: "path/to/file"
+          , mode: 0755
+          , size: 6
+          })
+  .write("hello\n")
+  .end()
+```
+
+This will create the directories if they're missing, and then write
+`hello\n` into the file, chmod it to 0755, and assert that 6 bytes have
+been written when it's done.
+
+```javascript
+fstream
+  .Writer({ path: "path/to/file"
+          , mode: 0755
+          , size: 6
+          , flags: "a"
+          })
+  .write("hello\n")
+  .end()
+```
+
+You can pass flags in, if you want to append to a file.
+
+```javascript
+fstream
+  .Writer({ path: "path/to/symlink"
+          , linkpath: "./file"
+          , SymbolicLink: true
+          , mode: "0755" // octal strings supported
+          })
+  .end()
+```
+
+If isSymbolicLink is a function, it'll be called, and if it returns
+true, then it'll treat it as a symlink.  If it's not a function, then
+any truish value will make a symlink, or you can set `type:
+'SymbolicLink'`, which does the same thing.
+
+Note that the linkpath is relative to the symbolic link location, not
+the parent dir or cwd.
+
+```javascript
+fstream
+  .Reader("path/to/dir")
+  .pipe(fstream.Writer("path/to/other/dir"))
+```
+
+This will do like `cp -Rp path/to/dir path/to/other/dir`.  If the other
+dir exists and isn't a directory, then it'll emit an error.  It'll also
+set the uid, gid, mode, etc. to be identical.  In this way, it's more
+like `rsync -a` than simply a copy.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/fstream.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/fstream.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/fstream.js	(revision 533)
@@ -0,0 +1,31 @@
+exports.Abstract = require("./lib/abstract.js")
+exports.Reader = require("./lib/reader.js")
+exports.Writer = require("./lib/writer.js")
+
+exports.File =
+  { Reader: require("./lib/file-reader.js")
+  , Writer: require("./lib/file-writer.js") }
+
+exports.Dir = 
+  { Reader : require("./lib/dir-reader.js")
+  , Writer : require("./lib/dir-writer.js") }
+
+exports.Link =
+  { Reader : require("./lib/link-reader.js")
+  , Writer : require("./lib/link-writer.js") }
+
+exports.Proxy =
+  { Reader : require("./lib/proxy-reader.js")
+  , Writer : require("./lib/proxy-writer.js") }
+
+exports.Reader.Dir = exports.DirReader = exports.Dir.Reader
+exports.Reader.File = exports.FileReader = exports.File.Reader
+exports.Reader.Link = exports.LinkReader = exports.Link.Reader
+exports.Reader.Proxy = exports.ProxyReader = exports.Proxy.Reader
+
+exports.Writer.Dir = exports.DirWriter = exports.Dir.Writer
+exports.Writer.File = exports.FileWriter = exports.File.Writer
+exports.Writer.Link = exports.LinkWriter = exports.Link.Writer
+exports.Writer.Proxy = exports.ProxyWriter = exports.Proxy.Writer
+
+exports.collect = require("./lib/collect.js")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/abstract.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/abstract.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/abstract.js	(revision 533)
@@ -0,0 +1,85 @@
+// the parent class for all fstreams.
+
+module.exports = Abstract
+
+var Stream = require("stream").Stream
+  , inherits = require("../../inherits/inherits.js")
+
+function Abstract () {
+  Stream.call(this)
+}
+
+inherits(Abstract, Stream)
+
+Abstract.prototype.on = function (ev, fn) {
+  if (ev === "ready" && this.ready) {
+    process.nextTick(fn.bind(this))
+  } else {
+    Stream.prototype.on.call(this, ev, fn)
+  }
+  return this
+}
+
+Abstract.prototype.abort = function () {
+  this._aborted = true
+  this.emit("abort")
+}
+
+Abstract.prototype.destroy = function () {}
+
+Abstract.prototype.warn = function (msg, code) {
+  var me = this
+    , er = decorate(msg, code, me)
+  if (!me.listeners("warn")) {
+    console.error("%s %s\n" +
+                  "path = %s\n" +
+                  "syscall = %s\n" +
+                  "fstream_type = %s\n" +
+                  "fstream_path = %s\n" +
+                  "fstream_unc_path = %s\n" +
+                  "fstream_class = %s\n" +
+                  "fstream_stack =\n%s\n",
+                  code || "UNKNOWN",
+                  er.stack,
+                  er.path,
+                  er.syscall,
+                  er.fstream_type,
+                  er.fstream_path,
+                  er.fstream_unc_path,
+                  er.fstream_class,
+                  er.fstream_stack.join("\n"))
+  } else {
+    me.emit("warn", er)
+  }
+}
+
+Abstract.prototype.info = function (msg, code) {
+  this.emit("info", msg, code)
+}
+
+Abstract.prototype.error = function (msg, code, th) {
+  var er = decorate(msg, code, this)
+  if (th) throw er
+  else this.emit("error", er)
+}
+
+function decorate (er, code, me) {
+  if (!(er instanceof Error)) er = new Error(er)
+  er.code = er.code || code
+  er.path = er.path || me.path
+  er.fstream_type = er.fstream_type || me.type
+  er.fstream_path = er.fstream_path || me.path
+  if (me._path !== me.path) {
+    er.fstream_unc_path = er.fstream_unc_path || me._path
+  }
+  if (me.linkpath) {
+    er.fstream_linkpath = er.fstream_linkpath || me.linkpath
+  }
+  er.fstream_class = er.fstream_class || me.constructor.name
+  er.fstream_stack = er.fstream_stack ||
+    new Error().stack.split(/\n/).slice(3).map(function (s) {
+      return s.replace(/^    at /, "")
+    })
+
+  return er
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/collect.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/collect.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/collect.js	(revision 533)
@@ -0,0 +1,67 @@
+module.exports = collect
+
+function collect (stream) {
+  if (stream._collected) return
+
+  stream._collected = true
+  stream.pause()
+
+  stream.on("data", save)
+  stream.on("end", save)
+  var buf = []
+  function save (b) {
+    if (typeof b === "string") b = new Buffer(b)
+    if (Buffer.isBuffer(b) && !b.length) return
+    buf.push(b)
+  }
+
+  stream.on("entry", saveEntry)
+  var entryBuffer = []
+  function saveEntry (e) {
+    collect(e)
+    entryBuffer.push(e)
+  }
+
+  stream.on("proxy", proxyPause)
+  function proxyPause (p) {
+    p.pause()
+  }
+
+
+  // replace the pipe method with a new version that will
+  // unlock the buffered stuff.  if you just call .pipe()
+  // without a destination, then it'll re-play the events.
+  stream.pipe = (function (orig) { return function (dest) {
+    // console.error(" === open the pipes", dest && dest.path)
+
+    // let the entries flow through one at a time.
+    // Once they're all done, then we can resume completely.
+    var e = 0
+    ;(function unblockEntry () {
+      var entry = entryBuffer[e++]
+      // console.error(" ==== unblock entry", entry && entry.path)
+      if (!entry) return resume()
+      entry.on("end", unblockEntry)
+      if (dest) dest.add(entry)
+      else stream.emit("entry", entry)
+    })()
+
+    function resume () {
+      stream.removeListener("entry", saveEntry)
+      stream.removeListener("data", save)
+      stream.removeListener("end", save)
+
+      stream.pipe = orig
+      if (dest) stream.pipe(dest)
+
+      buf.forEach(function (b) {
+        if (b) stream.emit("data", b)
+        else stream.emit("end")
+      })
+
+      stream.resume()
+    }
+
+    return dest
+  }})(stream.pipe)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-reader.js	(revision 533)
@@ -0,0 +1,250 @@
+// A thing that emits "entry" events with Reader objects
+// Pausing it causes it to stop emitting entry events, and also
+// pauses the current entry if there is one.
+
+module.exports = DirReader
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , fstream = require("../fstream.js")
+  , Reader = fstream.Reader
+  , inherits = require("../../inherits/inherits.js")
+  , mkdir = require("../../mkdirp")
+  , path = require("path")
+  , Reader = require("./reader.js")
+  , assert = require("assert").ok
+
+inherits(DirReader, Reader)
+
+function DirReader (props) {
+  var me = this
+  if (!(me instanceof DirReader)) throw new Error(
+    "DirReader must be called as constructor.")
+
+  // should already be established as a Directory type
+  if (props.type !== "Directory" || !props.Directory) {
+    throw new Error("Non-directory type "+ props.type)
+  }
+
+  me.entries = null
+  me._index = -1
+  me._paused = false
+  me._length = -1
+
+  if (props.sort) {
+    this.sort = props.sort
+  }
+
+  Reader.call(this, props)
+}
+
+DirReader.prototype._getEntries = function () {
+  var me = this
+
+  // race condition.  might pause() before calling _getEntries,
+  // and then resume, and try to get them a second time.
+  if (me._gotEntries) return
+  me._gotEntries = true
+
+  fs.readdir(me._path, function (er, entries) {
+    if (er) return me.error(er)
+
+    me.entries = entries
+
+    me.emit("entries", entries)
+    if (me._paused) me.once("resume", processEntries)
+    else processEntries()
+
+    function processEntries () {
+      me._length = me.entries.length
+      if (typeof me.sort === "function") {
+        me.entries = me.entries.sort(me.sort.bind(me))
+      }
+      me._read()
+    }
+  })
+}
+
+// start walking the dir, and emit an "entry" event for each one.
+DirReader.prototype._read = function () {
+  var me = this
+
+  if (!me.entries) return me._getEntries()
+
+  if (me._paused || me._currentEntry || me._aborted) {
+    // console.error("DR paused=%j, current=%j, aborted=%j", me._paused, !!me._currentEntry, me._aborted)
+    return
+  }
+
+  me._index ++
+  if (me._index >= me.entries.length) {
+    if (!me._ended) {
+      me._ended = true
+      me.emit("end")
+      me.emit("close")
+    }
+    return
+  }
+
+  // ok, handle this one, then.
+
+  // save creating a proxy, by stat'ing the thing now.
+  var p = path.resolve(me._path, me.entries[me._index])
+  assert(p !== me._path)
+  assert(me.entries[me._index])
+
+  // set this to prevent trying to _read() again in the stat time.
+  me._currentEntry = p
+  fs[ me.props.follow ? "stat" : "lstat" ](p, function (er, stat) {
+    if (er) return me.error(er)
+
+    var who = me._proxy || me
+
+    stat.path = p
+    stat.basename = path.basename(p)
+    stat.dirname = path.dirname(p)
+    var childProps = me.getChildProps.call(who, stat)
+    childProps.path = p
+    childProps.basename = path.basename(p)
+    childProps.dirname = path.dirname(p)
+
+    var entry = Reader(childProps, stat)
+
+    // console.error("DR Entry", p, stat.size)
+
+    me._currentEntry = entry
+
+    // "entry" events are for direct entries in a specific dir.
+    // "child" events are for any and all children at all levels.
+    // This nomenclature is not completely final.
+
+    entry.on("pause", function (who) {
+      if (!me._paused && !entry._disowned) {
+        me.pause(who)
+      }
+    })
+
+    entry.on("resume", function (who) {
+      if (me._paused && !entry._disowned) {
+        me.resume(who)
+      }
+    })
+
+    entry.on("stat", function (props) {
+      me.emit("_entryStat", entry, props)
+      if (entry._aborted) return
+      if (entry._paused) entry.once("resume", function () {
+        me.emit("entryStat", entry, props)
+      })
+      else me.emit("entryStat", entry, props)
+    })
+
+    entry.on("ready", function EMITCHILD () {
+      // console.error("DR emit child", entry._path)
+      if (me._paused) {
+        // console.error("  DR emit child - try again later")
+        // pause the child, and emit the "entry" event once we drain.
+        // console.error("DR pausing child entry")
+        entry.pause(me)
+        return me.once("resume", EMITCHILD)
+      }
+
+      // skip over sockets.  they can't be piped around properly,
+      // so there's really no sense even acknowledging them.
+      // if someone really wants to see them, they can listen to
+      // the "socket" events.
+      if (entry.type === "Socket") {
+        me.emit("socket", entry)
+      } else {
+        me.emitEntry(entry)
+      }
+    })
+
+    var ended = false
+    entry.on("close", onend)
+    entry.on("disown", onend)
+    function onend () {
+      if (ended) return
+      ended = true
+      me.emit("childEnd", entry)
+      me.emit("entryEnd", entry)
+      me._currentEntry = null
+      if (!me._paused) {
+        me._read()
+      }
+    }
+
+    // XXX Remove this.  Works in node as of 0.6.2 or so.
+    // Long filenames should not break stuff.
+    entry.on("error", function (er) {
+      if (entry._swallowErrors) {
+        me.warn(er)
+        entry.emit("end")
+        entry.emit("close")
+      } else {
+        me.emit("error", er)
+      }
+    })
+
+    // proxy up some events.
+    ; [ "child"
+      , "childEnd"
+      , "warn"
+      ].forEach(function (ev) {
+        entry.on(ev, me.emit.bind(me, ev))
+      })
+  })
+}
+
+DirReader.prototype.disown = function (entry) {
+  entry.emit("beforeDisown")
+  entry._disowned = true
+  entry.parent = entry.root = null
+  if (entry === this._currentEntry) {
+    this._currentEntry = null
+  }
+  entry.emit("disown")
+}
+
+DirReader.prototype.getChildProps = function (stat) {
+  return { depth: this.depth + 1
+         , root: this.root || this
+         , parent: this
+         , follow: this.follow
+         , filter: this.filter
+         , sort: this.props.sort
+         }
+}
+
+DirReader.prototype.pause = function (who) {
+  var me = this
+  if (me._paused) return
+  who = who || me
+  me._paused = true
+  if (me._currentEntry && me._currentEntry.pause) {
+    me._currentEntry.pause(who)
+  }
+  me.emit("pause", who)
+}
+
+DirReader.prototype.resume = function (who) {
+  var me = this
+  if (!me._paused) return
+  who = who || me
+
+  me._paused = false
+  // console.error("DR Emit Resume", me._path)
+  me.emit("resume", who)
+  if (me._paused) {
+    // console.error("DR Re-paused", me._path)
+    return
+  }
+
+  if (me._currentEntry) {
+    if (me._currentEntry.resume) me._currentEntry.resume(who)
+  } else me._read()
+}
+
+DirReader.prototype.emitEntry = function (entry) {
+  this.emit("entry", entry)
+  this.emit("child", entry)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-writer.js	(revision 533)
@@ -0,0 +1,171 @@
+// It is expected that, when .add() returns false, the consumer
+// of the DirWriter will pause until a "drain" event occurs. Note
+// that this is *almost always going to be the case*, unless the
+// thing being written is some sort of unsupported type, and thus
+// skipped over.
+
+module.exports = DirWriter
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , fstream = require("../fstream.js")
+  , Writer = require("./writer.js")
+  , inherits = require("../../inherits/inherits.js")
+  , mkdir = require("../../mkdirp")
+  , path = require("path")
+  , collect = require("./collect.js")
+
+inherits(DirWriter, Writer)
+
+function DirWriter (props) {
+  var me = this
+  if (!(me instanceof DirWriter)) me.error(
+    "DirWriter must be called as constructor.", null, true)
+
+  // should already be established as a Directory type
+  if (props.type !== "Directory" || !props.Directory) {
+    me.error("Non-directory type "+ props.type + " " +
+                    JSON.stringify(props), null, true)
+  }
+
+  Writer.call(this, props)
+}
+
+DirWriter.prototype._create = function () {
+  var me = this
+  mkdir(me._path, Writer.dirmode, function (er) {
+    if (er) return me.error(er)
+    // ready to start getting entries!
+    me.ready = true
+    me.emit("ready")
+    me._process()
+  })
+}
+
+// a DirWriter has an add(entry) method, but its .write() doesn't
+// do anything.  Why a no-op rather than a throw?  Because this
+// leaves open the door for writing directory metadata for
+// gnu/solaris style dumpdirs.
+DirWriter.prototype.write = function () {
+  return true
+}
+
+DirWriter.prototype.end = function () {
+  this._ended = true
+  this._process()
+}
+
+DirWriter.prototype.add = function (entry) {
+  var me = this
+
+  // console.error("\tadd", entry._path, "->", me._path)
+  collect(entry)
+  if (!me.ready || me._currentEntry) {
+    me._buffer.push(entry)
+    return false
+  }
+
+  // create a new writer, and pipe the incoming entry into it.
+  if (me._ended) {
+    return me.error("add after end")
+  }
+
+  me._buffer.push(entry)
+  me._process()
+
+  return 0 === this._buffer.length
+}
+
+DirWriter.prototype._process = function () {
+  var me = this
+
+  // console.error("DW Process p=%j", me._processing, me.basename)
+
+  if (me._processing) return
+
+  var entry = me._buffer.shift()
+  if (!entry) {
+    // console.error("DW Drain")
+    me.emit("drain")
+    if (me._ended) me._finish()
+    return
+  }
+
+  me._processing = true
+  // console.error("DW Entry", entry._path)
+
+  me.emit("entry", entry)
+
+  // ok, add this entry
+  //
+  // don't allow recursive copying
+  var p = entry
+  do {
+    var pp = p._path || p.path
+    if (pp === me.root._path || pp === me._path ||
+        (pp && pp.indexOf(me._path) === 0)) {
+      // console.error("DW Exit (recursive)", entry.basename, me._path)
+      me._processing = false
+      if (entry._collected) entry.pipe()
+      return me._process()
+    }
+  } while (p = p.parent)
+
+  // console.error("DW not recursive")
+
+  // chop off the entry's root dir, replace with ours
+  var props = { parent: me
+              , root: me.root || me
+              , type: entry.type
+              , depth: me.depth + 1 }
+
+  var p = entry._path || entry.path || entry.props.path
+  if (entry.parent) {
+    p = p.substr(entry.parent._path.length + 1)
+  }
+  // get rid of any ../../ shenanigans
+  props.path = path.join(me.path, path.join("/", p))
+
+  // if i have a filter, the child should inherit it.
+  props.filter = me.filter
+
+  // all the rest of the stuff, copy over from the source.
+  Object.keys(entry.props).forEach(function (k) {
+    if (!props.hasOwnProperty(k)) {
+      props[k] = entry.props[k]
+    }
+  })
+
+  // not sure at this point what kind of writer this is.
+  var child = me._currentChild = new Writer(props)
+  child.on("ready", function () {
+    // console.error("DW Child Ready", child.type, child._path)
+    // console.error("  resuming", entry._path)
+    entry.pipe(child)
+    entry.resume()
+  })
+
+  // XXX Make this work in node.
+  // Long filenames should not break stuff.
+  child.on("error", function (er) {
+    if (child._swallowErrors) {
+      me.warn(er)
+      child.emit("end")
+      child.emit("close")
+    } else {
+      me.emit("error", er)
+    }
+  })
+
+  // we fire _end internally *after* end, so that we don't move on
+  // until any "end" listeners have had their chance to do stuff.
+  child.on("close", onend)
+  var ended = false
+  function onend () {
+    if (ended) return
+    ended = true
+    // console.error("* DW Child end", child.basename)
+    me._currentChild = null
+    me._processing = false
+    me._process()
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-reader.js	(revision 533)
@@ -0,0 +1,147 @@
+// Basically just a wrapper around an fs.ReadStream
+
+module.exports = FileReader
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , fstream = require("../fstream.js")
+  , Reader = fstream.Reader
+  , inherits = require("../../inherits/inherits.js")
+  , mkdir = require("../../mkdirp")
+  , Reader = require("./reader.js")
+  , EOF = {EOF: true}
+  , CLOSE = {CLOSE: true}
+
+inherits(FileReader, Reader)
+
+function FileReader (props) {
+  // console.error("    FR create", props.path, props.size, new Error().stack)
+  var me = this
+  if (!(me instanceof FileReader)) throw new Error(
+    "FileReader must be called as constructor.")
+
+  // should already be established as a File type
+  // XXX Todo: preserve hardlinks by tracking dev+inode+nlink,
+  // with a HardLinkReader class.
+  if (!((props.type === "Link" && props.Link) ||
+        (props.type === "File" && props.File))) {
+    throw new Error("Non-file type "+ props.type)
+  }
+
+  me._buffer = []
+  me._bytesEmitted = 0
+  Reader.call(me, props)
+}
+
+FileReader.prototype._getStream = function () {
+  var me = this
+    , stream = me._stream = fs.createReadStream(me._path, me.props)
+
+  if (me.props.blksize) {
+    stream.bufferSize = me.props.blksize
+  }
+
+  stream.on("open", me.emit.bind(me, "open"))
+
+  stream.on("data", function (c) {
+    // console.error("\t\t%d %s", c.length, me.basename)
+    me._bytesEmitted += c.length
+    // no point saving empty chunks
+    if (!c.length) return
+    else if (me._paused || me._buffer.length) {
+      me._buffer.push(c)
+      me._read()
+    } else me.emit("data", c)
+  })
+
+  stream.on("end", function () {
+    if (me._paused || me._buffer.length) {
+      // console.error("FR Buffering End", me._path)
+      me._buffer.push(EOF)
+      me._read()
+    } else {
+      me.emit("end")
+    }
+
+    if (me._bytesEmitted !== me.props.size) {
+      me.error("Didn't get expected byte count\n"+
+               "expect: "+me.props.size + "\n" +
+               "actual: "+me._bytesEmitted)
+    }
+  })
+
+  stream.on("close", function () {
+    if (me._paused || me._buffer.length) {
+      // console.error("FR Buffering Close", me._path)
+      me._buffer.push(CLOSE)
+      me._read()
+    } else {
+      // console.error("FR close 1", me._path)
+      me.emit("close")
+    }
+  })
+
+  me._read()
+}
+
+FileReader.prototype._read = function () {
+  var me = this
+  // console.error("FR _read", me._path)
+  if (me._paused) {
+    // console.error("FR _read paused", me._path)
+    return
+  }
+
+  if (!me._stream) {
+    // console.error("FR _getStream calling", me._path)
+    return me._getStream()
+  }
+
+  // clear out the buffer, if there is one.
+  if (me._buffer.length) {
+    // console.error("FR _read has buffer", me._buffer.length, me._path)
+    var buf = me._buffer
+    for (var i = 0, l = buf.length; i < l; i ++) {
+      var c = buf[i]
+      if (c === EOF) {
+        // console.error("FR Read emitting buffered end", me._path)
+        me.emit("end")
+      } else if (c === CLOSE) {
+        // console.error("FR Read emitting buffered close", me._path)
+        me.emit("close")
+      } else {
+        // console.error("FR Read emitting buffered data", me._path)
+        me.emit("data", c)
+      }
+
+      if (me._paused) {
+        // console.error("FR Read Re-pausing at "+i, me._path)
+        me._buffer = buf.slice(i)
+        return
+      }
+    }
+    me._buffer.length = 0
+  }
+  // console.error("FR _read done")
+  // that's about all there is to it.
+}
+
+FileReader.prototype.pause = function (who) {
+  var me = this
+  // console.error("FR Pause", me._path)
+  if (me._paused) return
+  who = who || me
+  me._paused = true
+  if (me._stream) me._stream.pause()
+  me.emit("pause", who)
+}
+
+FileReader.prototype.resume = function (who) {
+  var me = this
+  // console.error("FR Resume", me._path)
+  if (!me._paused) return
+  who = who || me
+  me.emit("resume", who)
+  me._paused = false
+  if (me._stream) me._stream.resume()
+  me._read()
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-writer.js	(revision 533)
@@ -0,0 +1,95 @@
+module.exports = FileWriter
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , mkdir = require("../../mkdirp")
+  , Writer = require("./writer.js")
+  , inherits = require("../../inherits/inherits.js")
+  , EOF = {}
+
+inherits(FileWriter, Writer)
+
+function FileWriter (props) {
+  var me = this
+  if (!(me instanceof FileWriter)) throw new Error(
+    "FileWriter must be called as constructor.")
+
+  // should already be established as a File type
+  if (props.type !== "File" || !props.File) {
+    throw new Error("Non-file type "+ props.type)
+  }
+
+  me._buffer = []
+  me._bytesWritten = 0
+
+  Writer.call(this, props)
+}
+
+FileWriter.prototype._create = function () {
+  var me = this
+  if (me._stream) return
+
+  var so = {}
+  if (me.props.flags) so.flags = me.props.flags
+  so.mode = Writer.filemode
+  if (me._old && me._old.blksize) so.bufferSize = me._old.blksize
+
+  me._stream = fs.createWriteStream(me._path, so)
+
+  me._stream.on("open", function (fd) {
+    me.ready = true
+    me._buffer.forEach(function (c) {
+      if (c === EOF) me._stream.end()
+      else me._stream.write(c)
+    })
+    me.emit("ready")
+  })
+
+  me._stream.on("drain", function () { me.emit("drain") })
+
+  me._stream.on("close", function () {
+    // console.error("\n\nFW Stream Close", me._path, me.size)
+    me._finish()
+  })
+}
+
+FileWriter.prototype.write = function (c) {
+  var me = this
+
+  me._bytesWritten += c.length
+
+  if (!me.ready) {
+    me._buffer.push(c)
+    return false
+  }
+
+  var ret = me._stream.write(c)
+  // console.error("\t-- fw wrote, _stream says", ret, me._stream._queue.length)
+
+  // allow 2 buffered writes, because otherwise there's just too
+  // much stop and go bs.
+  return ret || (me._stream._queue && me._stream._queue.length <= 2)
+}
+
+FileWriter.prototype.end = function (c) {
+  var me = this
+
+  if (c) me.write(c)
+
+  if (!me.ready) {
+    me._buffer.push(EOF)
+    return false
+  }
+
+  return me._stream.end()
+}
+
+FileWriter.prototype._finish = function () {
+  var me = this
+  if (typeof me.size === "number" && me._bytesWritten != me.size) {
+    me.error(
+      "Did not get expected byte count.\n" +
+      "expect: " + me.size + "\n" +
+      "actual: " + me._bytesWritten)
+  }
+  Writer.prototype._finish.call(me)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/get-type.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/get-type.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/get-type.js	(revision 533)
@@ -0,0 +1,32 @@
+module.exports = getType
+
+function getType (st) {
+  var types =
+      [ "Directory"
+      , "File"
+      , "SymbolicLink"
+      , "Link" // special for hardlinks from tarballs
+      , "BlockDevice"
+      , "CharacterDevice"
+      , "FIFO"
+      , "Socket" ]
+    , type
+
+  if (st.type && -1 !== types.indexOf(st.type)) {
+    st[st.type] = true
+    return st.type
+  }
+
+  for (var i = 0, l = types.length; i < l; i ++) {
+    type = types[i]
+    var is = st[type] || st["is" + type]
+    if (typeof is === "function") is = is.call(st)
+    if (is) {
+      st[type] = true
+      st.type = type
+      return type
+    }
+  }
+
+  return null
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-reader.js	(revision 533)
@@ -0,0 +1,54 @@
+// Basically just a wrapper around an fs.readlink
+//
+// XXX: Enhance this to support the Link type, by keeping
+// a lookup table of {<dev+inode>:<path>}, so that hardlinks
+// can be preserved in tarballs.
+
+module.exports = LinkReader
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , fstream = require("../fstream.js")
+  , inherits = require("../../inherits/inherits.js")
+  , mkdir = require("../../mkdirp")
+  , Reader = require("./reader.js")
+
+inherits(LinkReader, Reader)
+
+function LinkReader (props) {
+  var me = this
+  if (!(me instanceof LinkReader)) throw new Error(
+    "LinkReader must be called as constructor.")
+
+  if (!((props.type === "Link" && props.Link) ||
+        (props.type === "SymbolicLink" && props.SymbolicLink))) {
+    throw new Error("Non-link type "+ props.type)
+  }
+
+  Reader.call(me, props)
+}
+
+// When piping a LinkReader into a LinkWriter, we have to
+// already have the linkpath property set, so that has to
+// happen *before* the "ready" event, which means we need to
+// override the _stat method.
+LinkReader.prototype._stat = function (currentStat) {
+  var me = this
+  fs.readlink(me._path, function (er, linkpath) {
+    if (er) return me.error(er)
+    me.linkpath = me.props.linkpath = linkpath
+    me.emit("linkpath", linkpath)
+    Reader.prototype._stat.call(me, currentStat)
+  })
+}
+
+LinkReader.prototype._read = function () {
+  var me = this
+  if (me._paused) return
+  // basically just a no-op, since we got all the info we need
+  // from the _stat method
+  if (!me._ended) {
+    me.emit("end")
+    me.emit("close")
+    me._ended = true
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-writer.js	(revision 533)
@@ -0,0 +1,95 @@
+
+module.exports = LinkWriter
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , Writer = require("./writer.js")
+  , inherits = require("../../inherits/inherits.js")
+  , path = require("path")
+  , rimraf = require("../../rimraf/rimraf.js")
+
+inherits(LinkWriter, Writer)
+
+function LinkWriter (props) {
+  var me = this
+  if (!(me instanceof LinkWriter)) throw new Error(
+    "LinkWriter must be called as constructor.")
+
+  // should already be established as a Link type
+  if (!((props.type === "Link" && props.Link) ||
+        (props.type === "SymbolicLink" && props.SymbolicLink))) {
+    throw new Error("Non-link type "+ props.type)
+  }
+
+  if (props.linkpath === "") props.linkpath = "."
+  if (!props.linkpath) {
+    me.error("Need linkpath property to create " + props.type)
+  }
+
+  Writer.call(this, props)
+}
+
+LinkWriter.prototype._create = function () {
+  // console.error(" LW _create")
+  var me = this
+    , hard = me.type === "Link" || process.platform === "win32"
+    , link = hard ? "link" : "symlink"
+    , lp = hard ? path.resolve(me.dirname, me.linkpath) : me.linkpath
+
+  // can only change the link path by clobbering
+  // For hard links, let's just assume that's always the case, since
+  // there's no good way to read them if we don't already know.
+  if (hard) return clobber(me, lp, link)
+
+  fs.readlink(me._path, function (er, p) {
+    // only skip creation if it's exactly the same link
+    if (p && p === lp) return finish(me)
+    clobber(me, lp, link)
+  })
+}
+
+function clobber (me, lp, link) {
+  rimraf(me._path, function (er) {
+    if (er) return me.error(er)
+    create(me, lp, link)
+  })
+}
+
+function create (me, lp, link) {
+  fs[link](lp, me._path, function (er) {
+    // if this is a hard link, and we're in the process of writing out a
+    // directory, it's very possible that the thing we're linking to
+    // doesn't exist yet (especially if it was intended as a symlink),
+    // so swallow ENOENT errors here and just soldier in.
+    // Additionally, an EPERM or EACCES can happen on win32 if it's trying
+    // to make a link to a directory.  Again, just skip it.
+    // A better solution would be to have fs.symlink be supported on
+    // windows in some nice fashion.
+    if (er) {
+      if ((er.code === "ENOENT" ||
+           er.code === "EACCES" ||
+           er.code === "EPERM" ) && process.platform === "win32") {
+        me.ready = true
+        me.emit("ready")
+        me.emit("end")
+        me.emit("close")
+        me.end = me._finish = function () {}
+      } else return me.error(er)
+    }
+    finish(me)
+  })
+}
+
+function finish (me) {
+  me.ready = true
+  me.emit("ready")
+  if (me._ended && !me._finished) me._finish()
+}
+
+LinkWriter.prototype.end = function () {
+  // console.error("LW finish in end")
+  this._ended = true
+  if (this.ready) {
+    this._finished = true
+    this._finish()
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-reader.js	(revision 533)
@@ -0,0 +1,93 @@
+// A reader for when we don't yet know what kind of thing
+// the thing is.
+
+module.exports = ProxyReader
+
+var Reader = require("./reader.js")
+  , getType = require("./get-type.js")
+  , inherits = require("../../inherits/inherits.js")
+  , fs = require("../../graceful-fs/graceful-fs.js")
+
+inherits(ProxyReader, Reader)
+
+function ProxyReader (props) {
+  var me = this
+  if (!(me instanceof ProxyReader)) throw new Error(
+    "ProxyReader must be called as constructor.")
+
+  me.props = props
+  me._buffer = []
+  me.ready = false
+
+  Reader.call(me, props)
+}
+
+ProxyReader.prototype._stat = function () {
+  var me = this
+    , props = me.props
+    // stat the thing to see what the proxy should be.
+    , stat = props.follow ? "stat" : "lstat"
+
+  fs[stat](props.path, function (er, current) {
+    var type
+    if (er || !current) {
+      type = "File"
+    } else {
+      type = getType(current)
+    }
+
+    props[type] = true
+    props.type = me.type = type
+
+    me._old = current
+    me._addProxy(Reader(props, current))
+  })
+}
+
+ProxyReader.prototype._addProxy = function (proxy) {
+  var me = this
+  if (me._proxyTarget) {
+    return me.error("proxy already set")
+  }
+
+  me._proxyTarget = proxy
+  proxy._proxy = me
+
+  ; [ "error"
+    , "data"
+    , "end"
+    , "close"
+    , "linkpath"
+    , "entry"
+    , "entryEnd"
+    , "child"
+    , "childEnd"
+    , "warn"
+    , "stat"
+    ].forEach(function (ev) {
+      // console.error("~~ proxy event", ev, me.path)
+      proxy.on(ev, me.emit.bind(me, ev))
+    })
+
+  me.emit("proxy", proxy)
+
+  proxy.on("ready", function () {
+    // console.error("~~ proxy is ready!", me.path)
+    me.ready = true
+    me.emit("ready")
+  })
+
+  var calls = me._buffer
+  me._buffer.length = 0
+  calls.forEach(function (c) {
+    proxy[c[0]].apply(proxy, c[1])
+  })
+}
+
+ProxyReader.prototype.pause = function () {
+  return this._proxyTarget ? this._proxyTarget.pause() : false
+}
+
+ProxyReader.prototype.resume = function () {
+  return this._proxyTarget ? this._proxyTarget.resume() : false
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-writer.js	(revision 533)
@@ -0,0 +1,109 @@
+// A writer for when we don't know what kind of thing
+// the thing is.  That is, it's not explicitly set,
+// so we're going to make it whatever the thing already
+// is, or "File"
+//
+// Until then, collect all events.
+
+module.exports = ProxyWriter
+
+var Writer = require("./writer.js")
+  , getType = require("./get-type.js")
+  , inherits = require("../../inherits/inherits.js")
+  , collect = require("./collect.js")
+  , fs = require("fs")
+
+inherits(ProxyWriter, Writer)
+
+function ProxyWriter (props) {
+  var me = this
+  if (!(me instanceof ProxyWriter)) throw new Error(
+    "ProxyWriter must be called as constructor.")
+
+  me.props = props
+  me._needDrain = false
+
+  Writer.call(me, props)
+}
+
+ProxyWriter.prototype._stat = function () {
+  var me = this
+    , props = me.props
+    // stat the thing to see what the proxy should be.
+    , stat = props.follow ? "stat" : "lstat"
+
+  fs[stat](props.path, function (er, current) {
+    var type
+    if (er || !current) {
+      type = "File"
+    } else {
+      type = getType(current)
+    }
+
+    props[type] = true
+    props.type = me.type = type
+
+    me._old = current
+    me._addProxy(Writer(props, current))
+  })
+}
+
+ProxyWriter.prototype._addProxy = function (proxy) {
+  // console.error("~~ set proxy", this.path)
+  var me = this
+  if (me._proxy) {
+    return me.error("proxy already set")
+  }
+
+  me._proxy = proxy
+  ; [ "ready"
+    , "error"
+    , "close"
+    , "pipe"
+    , "drain"
+    , "warn"
+    ].forEach(function (ev) {
+      proxy.on(ev, me.emit.bind(me, ev))
+    })
+
+  me.emit("proxy", proxy)
+
+  var calls = me._buffer
+  calls.forEach(function (c) {
+    // console.error("~~ ~~ proxy buffered call", c[0], c[1])
+    proxy[c[0]].call(proxy, c[1])
+  })
+  me._buffer.length = 0
+  if (me._needsDrain) me.emit("drain")
+}
+
+ProxyWriter.prototype.add = function (entry) {
+  // console.error("~~ proxy add")
+  collect(entry)
+
+  if (!this._proxy) {
+    this._buffer.push(["add", [entry]])
+    this._needDrain = true
+    return false
+  }
+  return this._proxy.add(entry)
+}
+
+ProxyWriter.prototype.write = function (c) {
+  // console.error("~~ proxy write")
+  if (!this._proxy) {
+    this._buffer.push(["write", [c]])
+    this._needDrain = true
+    return false
+  }
+  return this._proxy.write(c)
+}
+
+ProxyWriter.prototype.end = function (c) {
+  // console.error("~~ proxy end")
+  if (!this._proxy) {
+    this._buffer.push(["end", c])
+    return false
+  }
+  return this._proxy.end(c)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/reader.js	(revision 533)
@@ -0,0 +1,258 @@
+
+module.exports = Reader
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , Stream = require("stream").Stream
+  , inherits = require("../../inherits/inherits.js")
+  , path = require("path")
+  , getType = require("./get-type.js")
+  , hardLinks = Reader.hardLinks = {}
+  , Abstract = require("./abstract.js")
+
+// Must do this *before* loading the child classes
+inherits(Reader, Abstract)
+
+var DirReader = require("./dir-reader.js")
+  , FileReader = require("./file-reader.js")
+  , LinkReader = require("./link-reader.js")
+  , SocketReader = require("./socket-reader.js")
+  , ProxyReader = require("./proxy-reader.js")
+
+function Reader (props, currentStat) {
+  var me = this
+  if (!(me instanceof Reader)) return new Reader(props, currentStat)
+
+  if (typeof props === "string") {
+    props = { path: props }
+  }
+
+  if (!props.path) {
+    me.error("Must provide a path", null, true)
+  }
+
+  // polymorphism.
+  // call fstream.Reader(dir) to get a DirReader object, etc.
+  // Note that, unlike in the Writer case, ProxyReader is going
+  // to be the *normal* state of affairs, since we rarely know
+  // the type of a file prior to reading it.
+
+
+  var type
+    , ClassType
+
+  if (props.type && typeof props.type === "function") {
+    type = props.type
+    ClassType = type
+  } else {
+    type = getType(props)
+    ClassType = Reader
+  }
+
+  if (currentStat && !type) {
+    type = getType(currentStat)
+    props[type] = true
+    props.type = type
+  }
+
+  switch (type) {
+    case "Directory":
+      ClassType = DirReader
+      break
+
+    case "Link":
+      // XXX hard links are just files.
+      // However, it would be good to keep track of files' dev+inode
+      // and nlink values, and create a HardLinkReader that emits
+      // a linkpath value of the original copy, so that the tar
+      // writer can preserve them.
+      // ClassType = HardLinkReader
+      // break
+
+    case "File":
+      ClassType = FileReader
+      break
+
+    case "SymbolicLink":
+      ClassType = LinkReader
+      break
+
+    case "Socket":
+      ClassType = SocketReader
+      break
+
+    case null:
+      ClassType = ProxyReader
+      break
+  }
+
+  if (!(me instanceof ClassType)) {
+    return new ClassType(props)
+  }
+
+  Abstract.call(me)
+
+  me.readable = true
+  me.writable = false
+
+  me.type = type
+  me.props = props
+  me.depth = props.depth = props.depth || 0
+  me.parent = props.parent || null
+  me.root = props.root || (props.parent && props.parent.root) || me
+
+  me._path = me.path = path.resolve(props.path)
+  if (process.platform === "win32") {
+    me.path = me._path = me.path.replace(/\?/g, "_")
+    if (me._path.length >= 260) {
+      // how DOES one create files on the moon?
+      // if the path has spaces in it, then UNC will fail.
+      me._swallowErrors = true
+      //if (me._path.indexOf(" ") === -1) {
+        me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
+      //}
+    }
+  }
+  me.basename = props.basename = path.basename(me.path)
+  me.dirname = props.dirname = path.dirname(me.path)
+
+  // these have served their purpose, and are now just noisy clutter
+  props.parent = props.root = null
+
+  // console.error("\n\n\n%s setting size to", props.path, props.size)
+  me.size = props.size
+  me.filter = typeof props.filter === "function" ? props.filter : null
+  if (props.sort === "alpha") props.sort = alphasort
+
+  // start the ball rolling.
+  // this will stat the thing, and then call me._read()
+  // to start reading whatever it is.
+  // console.error("calling stat", props.path, currentStat)
+  me._stat(currentStat)
+}
+
+function alphasort (a, b) {
+  return a === b ? 0
+       : a.toLowerCase() > b.toLowerCase() ? 1
+       : a.toLowerCase() < b.toLowerCase() ? -1
+       : a > b ? 1
+       : -1
+}
+
+Reader.prototype._stat = function (currentStat) {
+  var me = this
+    , props = me.props
+    , stat = props.follow ? "stat" : "lstat"
+
+  // console.error("Reader._stat", me._path, currentStat)
+  if (currentStat) process.nextTick(statCb.bind(null, null, currentStat))
+  else fs[stat](me._path, statCb)
+
+
+  function statCb (er, props_) {
+    // console.error("Reader._stat, statCb", me._path, props_, props_.nlink)
+    if (er) return me.error(er)
+
+    Object.keys(props_).forEach(function (k) {
+      props[k] = props_[k]
+    })
+
+    // if it's not the expected size, then abort here.
+    if (undefined !== me.size && props.size !== me.size) {
+      return me.error("incorrect size")
+    }
+    me.size = props.size
+
+    var type = getType(props)
+    // special little thing for handling hardlinks.
+    if (type !== "Directory" && props.nlink && props.nlink > 1) {
+      var k = props.dev + ":" + props.ino
+      // console.error("Reader has nlink", me._path, k)
+      if (hardLinks[k] === me._path || !hardLinks[k]) hardLinks[k] = me._path
+      else {
+        // switch into hardlink mode.
+        type = me.type = me.props.type = "Link"
+        me.Link = me.props.Link = true
+        me.linkpath = me.props.linkpath = hardLinks[k]
+        // console.error("Hardlink detected, switching mode", me._path, me.linkpath)
+        // Setting __proto__ would arguably be the "correct"
+        // approach here, but that just seems too wrong.
+        me._stat = me._read = LinkReader.prototype._read
+      }
+    }
+
+    if (me.type && me.type !== type) {
+      me.error("Unexpected type: " + type)
+    }
+
+    // if the filter doesn't pass, then just skip over this one.
+    // still have to emit end so that dir-walking can move on.
+    if (me.filter) {
+      var who = me._proxy || me
+      // special handling for ProxyReaders
+      if (!me.filter.call(who, who, props)) {
+        if (!me._disowned) {
+          me.abort()
+          me.emit("end")
+          me.emit("close")
+        }
+        return
+      }
+    }
+
+    // last chance to abort or disown before the flow starts!
+    var events = ["_stat", "stat", "ready"]
+    var e = 0
+    ;(function go () {
+      if (me._aborted) {
+        me.emit("end")
+        me.emit("close")
+        return
+      }
+
+      if (me._paused) {
+        me.once("resume", go)
+        return
+      }
+
+      var ev = events[e ++]
+      if (!ev) return me._read()
+      me.emit(ev, props)
+      go()
+    })()
+  }
+}
+
+Reader.prototype.pipe = function (dest, opts) {
+  var me = this
+  if (typeof dest.add === "function") {
+    // piping to a multi-compatible, and we've got directory entries.
+    me.on("entry", function (entry) {
+      var ret = dest.add(entry)
+      if (false === ret) {
+        me.pause()
+      }
+    })
+  }
+
+  // console.error("R Pipe apply Stream Pipe")
+  return Stream.prototype.pipe.apply(this, arguments)
+}
+
+Reader.prototype.pause = function (who) {
+  this._paused = true
+  who = who || this
+  this.emit("pause", who)
+  if (this._stream) this._stream.pause(who)
+}
+
+Reader.prototype.resume = function (who) {
+  this._paused = false
+  who = who || this
+  this.emit("resume", who)
+  if (this._stream) this._stream.resume(who)
+  this._read()
+}
+
+Reader.prototype._read = function () {
+  this.error("Cannot read unknown type: "+this.type)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/socket-reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/socket-reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/socket-reader.js	(revision 533)
@@ -0,0 +1,38 @@
+// Just get the stats, and then don't do anything.
+// You can't really "read" from a socket.  You "connect" to it.
+// Mostly, this is here so that reading a dir with a socket in it
+// doesn't blow up.
+
+module.exports = SocketReader
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , fstream = require("../fstream.js")
+  , inherits = require("../../inherits/inherits.js")
+  , mkdir = require("../../mkdirp")
+  , Reader = require("./reader.js")
+
+inherits(SocketReader, Reader)
+
+function SocketReader (props) {
+  var me = this
+  if (!(me instanceof SocketReader)) throw new Error(
+    "SocketReader must be called as constructor.")
+
+  if (!(props.type === "Socket" && props.Socket)) {
+    throw new Error("Non-socket type "+ props.type)
+  }
+
+  Reader.call(me, props)
+}
+
+SocketReader.prototype._read = function () {
+  var me = this
+  if (me._paused) return
+  // basically just a no-op, since we got all the info we have
+  // from the _stat method
+  if (!me._ended) {
+    me.emit("end")
+    me.emit("close")
+    me._ended = true
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/writer.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/writer.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/writer.js	(revision 533)
@@ -0,0 +1,389 @@
+
+module.exports = Writer
+
+var fs = require("../../graceful-fs/graceful-fs.js")
+  , inherits = require("../../inherits/inherits.js")
+  , rimraf = require("../../rimraf/rimraf.js")
+  , mkdir = require("../../mkdirp")
+  , path = require("path")
+  , umask = process.platform === "win32" ? 0 : process.umask()
+  , getType = require("./get-type.js")
+  , Abstract = require("./abstract.js")
+
+// Must do this *before* loading the child classes
+inherits(Writer, Abstract)
+
+Writer.dirmode = 0777 & (~umask)
+Writer.filemode = 0666 & (~umask)
+
+var DirWriter = require("./dir-writer.js")
+  , LinkWriter = require("./link-writer.js")
+  , FileWriter = require("./file-writer.js")
+  , ProxyWriter = require("./proxy-writer.js")
+
+// props is the desired state.  current is optionally the current stat,
+// provided here so that subclasses can avoid statting the target
+// more than necessary.
+function Writer (props, current) {
+  var me = this
+
+  if (typeof props === "string") {
+    props = { path: props }
+  }
+
+  if (!props.path) me.error("Must provide a path", null, true)
+
+  // polymorphism.
+  // call fstream.Writer(dir) to get a DirWriter object, etc.
+  var type = getType(props)
+    , ClassType = Writer
+
+  switch (type) {
+    case "Directory":
+      ClassType = DirWriter
+      break
+    case "File":
+      ClassType = FileWriter
+      break
+    case "Link":
+    case "SymbolicLink":
+      ClassType = LinkWriter
+      break
+    case null:
+      // Don't know yet what type to create, so we wrap in a proxy.
+      ClassType = ProxyWriter
+      break
+  }
+
+  if (!(me instanceof ClassType)) return new ClassType(props)
+
+  // now get down to business.
+
+  Abstract.call(me)
+
+  // props is what we want to set.
+  // set some convenience properties as well.
+  me.type = props.type
+  me.props = props
+  me.depth = props.depth || 0
+  me.clobber = false === props.clobber ? props.clobber : true
+  me.parent = props.parent || null
+  me.root = props.root || (props.parent && props.parent.root) || me
+
+  me._path = me.path = path.resolve(props.path)
+  if (process.platform === "win32") {
+    me.path = me._path = me.path.replace(/\?/g, "_")
+    if (me._path.length >= 260) {
+      me._swallowErrors = true
+      me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
+    }
+  }
+  me.basename = path.basename(props.path)
+  me.dirname = path.dirname(props.path)
+  me.linkpath = props.linkpath || null
+
+  props.parent = props.root = null
+
+  // console.error("\n\n\n%s setting size to", props.path, props.size)
+  me.size = props.size
+
+  if (typeof props.mode === "string") {
+    props.mode = parseInt(props.mode, 8)
+  }
+
+  me.readable = false
+  me.writable = true
+
+  // buffer until ready, or while handling another entry
+  me._buffer = []
+  me.ready = false
+
+  me.filter = typeof props.filter === "function" ? props.filter: null
+
+  // start the ball rolling.
+  // this checks what's there already, and then calls
+  // me._create() to call the impl-specific creation stuff.
+  me._stat(current)
+}
+
+// Calling this means that it's something we can't create.
+// Just assert that it's already there, otherwise raise a warning.
+Writer.prototype._create = function () {
+  var me = this
+  fs[me.props.follow ? "stat" : "lstat"](me._path, function (er, current) {
+    if (er) {
+      return me.warn("Cannot create " + me._path + "\n" +
+                     "Unsupported type: "+me.type, "ENOTSUP")
+    }
+    me._finish()
+  })
+}
+
+Writer.prototype._stat = function (current) {
+  var me = this
+    , props = me.props
+    , stat = props.follow ? "stat" : "lstat"
+    , who = me._proxy || me
+
+  if (current) statCb(null, current)
+  else fs[stat](me._path, statCb)
+
+  function statCb (er, current) {
+    if (me.filter && !me.filter.call(who, who, current)) {
+      me._aborted = true
+      me.emit("end")
+      me.emit("close")
+      return
+    }
+
+    // if it's not there, great.  We'll just create it.
+    // if it is there, then we'll need to change whatever differs
+    if (er || !current) {
+      return create(me)
+    }
+
+    me._old = current
+    var currentType = getType(current)
+
+    // if it's a type change, then we need to clobber or error.
+    // if it's not a type change, then let the impl take care of it.
+    if (currentType !== me.type) {
+      return rimraf(me._path, function (er) {
+        if (er) return me.error(er)
+        me._old = null
+        create(me)
+      })
+    }
+
+    // otherwise, just handle in the app-specific way
+    // this creates a fs.WriteStream, or mkdir's, or whatever
+    create(me)
+  }
+}
+
+function create (me) {
+  // console.error("W create", me._path, Writer.dirmode)
+
+  // XXX Need to clobber non-dirs that are in the way,
+  // unless { clobber: false } in the props.
+  mkdir(path.dirname(me._path), Writer.dirmode, function (er, made) {
+    // console.error("W created", path.dirname(me._path), er)
+    if (er) return me.error(er)
+
+    // later on, we have to set the mode and owner for these
+    me._madeDir = made
+    return me._create()
+  })
+}
+
+function endChmod (me, want, current, path, cb) {
+    var wantMode = want.mode
+      , chmod = want.follow || me.type !== "SymbolicLink"
+              ? "chmod" : "lchmod"
+
+  if (!fs[chmod]) return cb()
+  if (typeof wantMode !== "number") return cb()
+
+  var curMode = current.mode & 0777
+  wantMode = wantMode & 0777
+  if (wantMode === curMode) return cb()
+
+  fs[chmod](path, wantMode, cb)
+}
+
+
+function endChown (me, want, current, path, cb) {
+  // Don't even try it unless root.  Too easy to EPERM.
+  if (process.platform === "win32") return cb()
+  if (!process.getuid || !process.getuid() === 0) return cb()
+  if (typeof want.uid !== "number" &&
+      typeof want.gid !== "number" ) return cb()
+
+  if (current.uid === want.uid &&
+      current.gid === want.gid) return cb()
+
+  var chown = (me.props.follow || me.type !== "SymbolicLink")
+            ? "chown" : "lchown"
+  if (!fs[chown]) return cb()
+
+  if (typeof want.uid !== "number") want.uid = current.uid
+  if (typeof want.gid !== "number") want.gid = current.gid
+
+  fs[chown](path, want.uid, want.gid, cb)
+}
+
+function endUtimes (me, want, current, path, cb) {
+  if (!fs.utimes || process.platform === "win32") return cb()
+
+  var utimes = (want.follow || me.type !== "SymbolicLink")
+             ? "utimes" : "lutimes"
+
+  if (utimes === "lutimes" && !fs[utimes]) {
+    utimes = "utimes"
+  }
+
+  if (!fs[utimes]) return cb()
+
+  var curA = current.atime
+    , curM = current.mtime
+    , meA = want.atime
+    , meM = want.mtime
+
+  if (meA === undefined) meA = curA
+  if (meM === undefined) meM = curM
+
+  if (!isDate(meA)) meA = new Date(meA)
+  if (!isDate(meM)) meA = new Date(meM)
+
+  if (meA.getTime() === curA.getTime() &&
+      meM.getTime() === curM.getTime()) return cb()
+
+  fs[utimes](path, meA, meM, cb)
+}
+
+
+// XXX This function is beastly.  Break it up!
+Writer.prototype._finish = function () {
+  var me = this
+
+  // console.error(" W Finish", me._path, me.size)
+
+  // set up all the things.
+  // At this point, we're already done writing whatever we've gotta write,
+  // adding files to the dir, etc.
+  var todo = 0
+  var errState = null
+  var done = false
+
+  if (me._old) {
+    // the times will almost *certainly* have changed.
+    // adds the utimes syscall, but remove another stat.
+    me._old.atime = new Date(0)
+    me._old.mtime = new Date(0)
+    // console.error(" W Finish Stale Stat", me._path, me.size)
+    setProps(me._old)
+  } else {
+    var stat = me.props.follow ? "stat" : "lstat"
+    // console.error(" W Finish Stating", me._path, me.size)
+    fs[stat](me._path, function (er, current) {
+      // console.error(" W Finish Stated", me._path, me.size, current)
+      if (er) {
+        // if we're in the process of writing out a
+        // directory, it's very possible that the thing we're linking to
+        // doesn't exist yet (especially if it was intended as a symlink),
+        // so swallow ENOENT errors here and just soldier on.
+        if (er.code === "ENOENT" &&
+            (me.type === "Link" || me.type === "SymbolicLink") &&
+            process.platform === "win32") {
+          me.ready = true
+          me.emit("ready")
+          me.emit("end")
+          me.emit("close")
+          me.end = me._finish = function () {}
+          return
+        } else return me.error(er)
+      }
+      setProps(me._old = current)
+    })
+  }
+
+  return
+
+  function setProps (current) {
+    endChmod(me, me.props, current, me._path, next("chmod"))
+    endChown(me, me.props, current, me._path, next("chown"))
+    endUtimes(me, me.props, current, me._path, next("chown"))
+  }
+
+  function next (what) {
+    todo ++
+    return function (er) {
+      // console.error("   W Finish", what, todo)
+      if (errState) return
+      if (er) {
+        er.fstream_finish_call = what
+        return me.error(errState = er)
+      }
+      if (--todo > 0) return
+      if (done) return
+      done = true
+
+      // we may still need to set the mode/etc. on some parent dirs
+      // that were created previously.  delay end/close until then.
+      if (!me._madeDir) return end()
+      else endMadeDir(me, me._path, end)
+
+      function end (er) {
+        if (er) {
+          er.fstream_finish_call = "setupMadeDir"
+          return me.error(er)
+        }
+        // all the props have been set, so we're completely done.
+        me.emit("end")
+        me.emit("close")
+      }
+    }
+  }
+}
+
+function endMadeDir (me, p, cb) {
+  var made = me._madeDir
+  // everything *between* made and path.dirname(me._path)
+  // needs to be set up.  Note that this may just be one dir.
+  var d = path.dirname(p)
+
+  endMadeDir_(me, d, function (er) {
+    if (er) return cb(er)
+    if (d === made) {
+      return cb()
+    }
+    endMadeDir(me, d, cb)
+  })
+}
+
+function endMadeDir_ (me, p, cb) {
+  var dirProps = {}
+  Object.keys(me.props).forEach(function (k) {
+    dirProps[k] = me.props[k]
+
+    // only make non-readable dirs if explicitly requested.
+    if (k === "mode" && me.type !== "Directory") {
+      dirProps[k] = dirProps[k] | 0111
+    }
+  })
+
+  var todo = 3
+  , errState = null
+  fs.stat(p, function (er, current) {
+    if (er) return cb(errState = er)
+    endChmod(me, dirProps, current, p, next)
+    endChown(me, dirProps, current, p, next)
+    endUtimes(me, dirProps, current, p, next)
+  })
+
+  function next (er) {
+    if (errState) return
+    if (er) return cb(errState = er)
+    if (-- todo === 0) return cb()
+  }
+}
+
+Writer.prototype.pipe = function () {
+  this.error("Can't pipe from writable stream")
+}
+
+Writer.prototype.add = function () {
+  this.error("Cannot add to non-Directory type")
+}
+
+Writer.prototype.write = function () {
+  return true
+}
+
+function objectToString (d) {
+  return Object.prototype.toString.call(d)
+}
+
+function isDate(d) {
+  return typeof d === 'object' && objectToString(d) === '[object Date]';
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/LICENSE	(revision 533)
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+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 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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/README.md	(revision 533)
@@ -0,0 +1,5 @@
+Just like node's `fs` module, but it does an incremental back-off when
+EMFILE is encountered.
+
+Useful in asynchronous situations where one needs to try to open lots
+and lots of files.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/graceful-fs.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/graceful-fs.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/graceful-fs.js	(revision 533)
@@ -0,0 +1,312 @@
+// this keeps a queue of opened file descriptors, and will make
+// fs operations wait until some have closed before trying to open more.
+
+var fs = require("fs")
+
+// there is such a thing as TOO graceful.
+if (fs.open === gracefulOpen) return
+
+var queue = []
+  , constants = require("constants")
+
+exports = module.exports = fs
+fs._curOpen = 0
+
+fs.MIN_MAX_OPEN = 64
+fs.MAX_OPEN = 1024
+
+var originalOpen = fs.open
+  , originalOpenSync = fs.openSync
+  , originalClose = fs.close
+  , originalCloseSync = fs.closeSync
+
+
+// prevent EMFILE errors
+function OpenReq (path, flags, mode, cb) {
+  this.path = path
+  this.flags = flags
+  this.mode = mode
+  this.cb = cb
+}
+
+function noop () {}
+
+fs.open = gracefulOpen
+
+function gracefulOpen (path, flags, mode, cb) {
+  if (typeof mode === "function") cb = mode, mode = null
+  if (typeof cb !== "function") cb = noop
+
+  if (fs._curOpen >= fs.MAX_OPEN) {
+    queue.push(new OpenReq(path, flags, mode, cb))
+    setTimeout(flush)
+    return
+  }
+  open(path, flags, mode, function (er, fd) {
+    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
+      // that was too many.  reduce max, get back in queue.
+      // this should only happen once in a great while, and only
+      // if the ulimit -n is set lower than 1024.
+      fs.MAX_OPEN = fs._curOpen - 1
+      return fs.open(path, flags, mode, cb)
+    }
+    cb(er, fd)
+  })
+}
+
+function open (path, flags, mode, cb) {
+  cb = cb || noop
+  fs._curOpen ++
+  originalOpen.call(fs, path, flags, mode, function (er, fd) {
+    if (er) onclose()
+    cb(er, fd)
+  })
+}
+
+fs.openSync = function (path, flags, mode) {
+  var ret
+  ret = originalOpenSync.call(fs, path, flags, mode)
+  fs._curOpen ++
+  return ret
+}
+
+function onclose () {
+  fs._curOpen --
+  flush()
+}
+
+function flush () {
+  while (fs._curOpen < fs.MAX_OPEN) {
+    var req = queue.shift()
+    if (!req) return
+    open(req.path, req.flags || "r", req.mode || 0777, req.cb)
+  }
+}
+
+fs.close = function (fd, cb) {
+  cb = cb || noop
+  originalClose.call(fs, fd, function (er) {
+    onclose()
+    cb(er)
+  })
+}
+
+fs.closeSync = function (fd) {
+  onclose()
+  return originalCloseSync.call(fs, fd)
+}
+
+
+// (re-)implement some things that are known busted or missing.
+
+var constants = require("constants")
+
+// lchmod, broken prior to 0.6.2
+// back-port the fix here.
+if (constants.hasOwnProperty('O_SYMLINK') &&
+    process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
+  fs.lchmod = function (path, mode, callback) {
+    callback = callback || noop
+    fs.open( path
+           , constants.O_WRONLY | constants.O_SYMLINK
+           , mode
+           , function (err, fd) {
+      if (err) {
+        callback(err)
+        return
+      }
+      // prefer to return the chmod error, if one occurs,
+      // but still try to close, and report closing errors if they occur.
+      fs.fchmod(fd, mode, function (err) {
+        fs.close(fd, function(err2) {
+          callback(err || err2)
+        })
+      })
+    })
+  }
+
+  fs.lchmodSync = function (path, mode) {
+    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
+
+    // prefer to return the chmod error, if one occurs,
+    // but still try to close, and report closing errors if they occur.
+    var err, err2
+    try {
+      var ret = fs.fchmodSync(fd, mode)
+    } catch (er) {
+      err = er
+    }
+    try {
+      fs.closeSync(fd)
+    } catch (er) {
+      err2 = er
+    }
+    if (err || err2) throw (err || err2)
+    return ret
+  }
+}
+
+
+// lutimes implementation, or no-op
+if (!fs.lutimes) {
+  if (constants.hasOwnProperty("O_SYMLINK")) {
+    fs.lutimes = function (path, at, mt, cb) {
+      fs.open(path, constants.O_SYMLINK, function (er, fd) {
+        cb = cb || noop
+        if (er) return cb(er)
+        fs.futimes(fd, at, mt, function (er) {
+          fs.close(fd, function (er2) {
+            return cb(er || er2)
+          })
+        })
+      })
+    }
+
+    fs.lutimesSync = function (path, at, mt) {
+      var fd = fs.openSync(path, constants.O_SYMLINK)
+        , err
+        , err2
+        , ret
+
+      try {
+        var ret = fs.futimesSync(fd, at, mt)
+      } catch (er) {
+        err = er
+      }
+      try {
+        fs.closeSync(fd)
+      } catch (er) {
+        err2 = er
+      }
+      if (err || err2) throw (err || err2)
+      return ret
+    }
+
+  } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
+    // maybe utimensat will be bound soonish?
+    fs.lutimes = function (path, at, mt, cb) {
+      fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
+    }
+
+    fs.lutimesSync = function (path, at, mt) {
+      return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
+    }
+
+  } else {
+    fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
+    fs.lutimesSync = function () {}
+  }
+}
+
+
+// https://github.com/isaacs/node-graceful-fs/issues/4
+// Chown should not fail on einval or eperm if non-root.
+
+fs.chown = chownFix(fs.chown)
+fs.fchown = chownFix(fs.fchown)
+fs.lchown = chownFix(fs.lchown)
+
+fs.chownSync = chownFixSync(fs.chownSync)
+fs.fchownSync = chownFixSync(fs.fchownSync)
+fs.lchownSync = chownFixSync(fs.lchownSync)
+
+function chownFix (orig) {
+  if (!orig) return orig
+  return function (target, uid, gid, cb) {
+    return orig.call(fs, target, uid, gid, function (er, res) {
+      if (chownErOk(er)) er = null
+      cb(er, res)
+    })
+  }
+}
+
+function chownFixSync (orig) {
+  if (!orig) return orig
+  return function (target, uid, gid) {
+    try {
+      return orig.call(fs, target, uid, gid)
+    } catch (er) {
+      if (!chownErOk(er)) throw er
+    }
+  }
+}
+
+function chownErOk (er) {
+  // if there's no getuid, or if getuid() is something other than 0,
+  // and the error is EINVAL or EPERM, then just ignore it.
+  // This specific case is a silent failure in cp, install, tar,
+  // and most other unix tools that manage permissions.
+  // When running as root, or if other types of errors are encountered,
+  // then it's strict.
+  if (!er || (!process.getuid || process.getuid() !== 0)
+      && (er.code === "EINVAL" || er.code === "EPERM")) return true
+}
+
+
+// if lchmod/lchown do not exist, then make them no-ops
+if (!fs.lchmod) {
+  fs.lchmod = function (path, mode, cb) {
+    process.nextTick(cb)
+  }
+  fs.lchmodSync = function () {}
+}
+if (!fs.lchown) {
+  fs.lchown = function (path, uid, gid, cb) {
+    process.nextTick(cb)
+  }
+  fs.lchownSync = function () {}
+}
+
+
+
+// on Windows, A/V software can lock the directory, causing this
+// to fail with an EACCES or EPERM if the directory contains newly
+// created files.  Try again on failure, for up to 1 second.
+if (process.platform === "win32") {
+  var rename_ = fs.rename
+  fs.rename = function rename (from, to, cb) {
+    var start = Date.now()
+    rename_(from, to, function CB (er) {
+      if (er
+          && (er.code === "EACCES" || er.code === "EPERM")
+          && Date.now() - start < 1000) {
+        return rename_(from, to, CB)
+      }
+      cb(er)
+    })
+  }
+}
+
+
+// if read() returns EAGAIN, then just try it again.
+var read = fs.read
+fs.read = function (fd, buffer, offset, length, position, callback_) {
+  var callback
+  if (callback_ && typeof callback_ === 'function') {
+    var eagCounter = 0
+    callback = function (er, _, __) {
+      if (er && er.code === 'EAGAIN' && eagCounter < 10) {
+        eagCounter ++
+        return read.call(fs, fd, buffer, offset, length, position, callback)
+      }
+      callback_.apply(this, arguments)
+    }
+  }
+  return read.call(fs, fd, buffer, offset, length, position, callback)
+}
+
+var readSync = fs.readSync
+fs.readSync = function (fd, buffer, offset, length, position) {
+  var eagCounter = 0
+  while (true) {
+    try {
+      return readSync.call(fs, fd, buffer, offset, length, position)
+    } catch (er) {
+      if (er.code === 'EAGAIN' && eagCounter < 10) {
+        eagCounter ++
+        continue
+      }
+      throw er
+    }
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/README.md	(revision 533)
@@ -0,0 +1,51 @@
+A dead simple way to do inheritance in JS.
+
+    var inherits = require("inherits")
+
+    function Animal () {
+      this.alive = true
+    }
+    Animal.prototype.say = function (what) {
+      console.log(what)
+    }
+
+    inherits(Dog, Animal)
+    function Dog () {
+      Dog.super.apply(this)
+    }
+    Dog.prototype.sniff = function () {
+      this.say("sniff sniff")
+    }
+    Dog.prototype.bark = function () {
+      this.say("woof woof")
+    }
+
+    inherits(Chihuahua, Dog)
+    function Chihuahua () {
+      Chihuahua.super.apply(this)
+    }
+    Chihuahua.prototype.bark = function () {
+      this.say("yip yip")
+    }
+
+    // also works
+    function Cat () {
+      Cat.super.apply(this)
+    }
+    Cat.prototype.hiss = function () {
+      this.say("CHSKKSS!!")
+    }
+    inherits(Cat, Animal, {
+      meow: function () { this.say("miao miao") }
+    })
+    Cat.prototype.purr = function () {
+      this.say("purr purr")
+    }
+
+
+    var c = new Chihuahua
+    assert(c instanceof Chihuahua)
+    assert(c instanceof Dog)
+    assert(c instanceof Animal)
+
+The actual function is laughably small.  10-lines small.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/inherits.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/inherits.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/inherits.js	(revision 533)
@@ -0,0 +1,29 @@
+module.exports = inherits
+
+function inherits (c, p, proto) {
+  proto = proto || {}
+  var e = {}
+  ;[c.prototype, proto].forEach(function (s) {
+    Object.getOwnPropertyNames(s).forEach(function (k) {
+      e[k] = Object.getOwnPropertyDescriptor(s, k)
+    })
+  })
+  c.prototype = Object.create(p.prototype, e)
+  c.super = p
+}
+
+//function Child () {
+//  Child.super.call(this)
+//  console.error([this
+//                ,this.constructor
+//                ,this.constructor === Child
+//                ,this.constructor.super === Parent
+//                ,Object.getPrototypeOf(this) === Child.prototype
+//                ,Object.getPrototypeOf(Object.getPrototypeOf(this))
+//                 === Parent.prototype
+//                ,this instanceof Child
+//                ,this instanceof Parent])
+//}
+//function Parent () {}
+//inherits(Child, Parent)
+//new Child
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/LICENSE	(revision 533)
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/README.markdown
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/README.markdown	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/README.markdown	(revision 533)
@@ -0,0 +1,61 @@
+mkdirp
+======
+
+Like `mkdir -p`, but in node.js!
+
+[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
+
+example
+=======
+
+pow.js
+------
+    var mkdirp = require('mkdirp');
+    
+    mkdirp('/tmp/foo/bar/baz', function (err) {
+        if (err) console.error(err)
+        else console.log('pow!')
+    });
+
+Output
+    pow!
+
+And now /tmp/foo/bar/baz exists, huzzah!
+
+methods
+=======
+
+var mkdirp = require('mkdirp');
+
+mkdirp(dir, mode, cb)
+---------------------
+
+Create a new directory and any necessary subdirectories at `dir` with octal
+permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+`cb(err, made)` fires with the error or the first directory `made`
+that had to be created, if any.
+
+mkdirp.sync(dir, mode)
+----------------------
+
+Synchronously create a new directory and any necessary subdirectories at `dir`
+with octal permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+Returns the first directory that had to be created, if any.
+
+install
+=======
+
+With [npm](http://npmjs.org) do:
+
+    npm install mkdirp
+
+license
+=======
+
+MIT/X11
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/index.js	(revision 533)
@@ -0,0 +1,82 @@
+var path = require('path');
+var fs = require('fs');
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, mode, f, made) {
+    if (typeof mode === 'function' || mode === undefined) {
+        f = mode;
+        mode = 0777 & (~process.umask());
+    }
+    if (!made) made = null;
+
+    var cb = f || function () {};
+    if (typeof mode === 'string') mode = parseInt(mode, 8);
+    p = path.resolve(p);
+
+    fs.mkdir(p, mode, function (er) {
+        if (!er) {
+            made = made || p;
+            return cb(null, made);
+        }
+        switch (er.code) {
+            case 'ENOENT':
+                mkdirP(path.dirname(p), mode, function (er, made) {
+                    if (er) cb(er, made);
+                    else mkdirP(p, mode, cb, made);
+                });
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                fs.stat(p, function (er2, stat) {
+                    // if the stat fails, then that's super weird.
+                    // let the original error be the failure reason.
+                    if (er2 || !stat.isDirectory()) cb(er, made)
+                    else cb(null, made);
+                });
+                break;
+        }
+    });
+}
+
+mkdirP.sync = function sync (p, mode, made) {
+    if (mode === undefined) {
+        mode = 0777 & (~process.umask());
+    }
+    if (!made) made = null;
+
+    if (typeof mode === 'string') mode = parseInt(mode, 8);
+    p = path.resolve(p);
+
+    try {
+        fs.mkdirSync(p, mode);
+        made = made || p;
+    }
+    catch (err0) {
+        switch (err0.code) {
+            case 'ENOENT' :
+                made = sync(path.dirname(p), mode, made);
+                sync(p, mode, made);
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                var stat;
+                try {
+                    stat = fs.statSync(p);
+                }
+                catch (err1) {
+                    throw err0;
+                }
+                if (!stat.isDirectory()) throw err0;
+                break;
+        }
+    }
+
+    return made;
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/AUTHORS
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/AUTHORS	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/AUTHORS	(revision 533)
@@ -0,0 +1,6 @@
+# Authors sorted by whether or not they're me.
+Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)
+Wayne Larsen <wayne@larsen.st> (http://github.com/wvl)
+ritch <skawful@gmail.com>
+Marcel Laverdet
+Yosef Dinerstein <yosefd@microsoft.com>
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/LICENSE	(revision 533)
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+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 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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/README.md	(revision 533)
@@ -0,0 +1,21 @@
+A `rm -rf` for node.
+
+Install with `npm install rimraf`, or just drop rimraf.js somewhere.
+
+## API
+
+`rimraf(f, callback)`
+
+The callback will be called with an error if there is one.  Certain
+errors are handled for you:
+
+* `EBUSY` -  rimraf will back off a maximum of opts.maxBusyTries times
+  before giving up.
+* `EMFILE` - If too many file descriptors get opened, rimraf will
+  patiently wait until more become available.
+
+
+## rimraf.sync
+
+It can remove stuff synchronously, too.  But that's not so good.  Use
+the async API.  It's better.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/rimraf.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/rimraf.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/rimraf.js	(revision 533)
@@ -0,0 +1,161 @@
+module.exports = rimraf
+rimraf.sync = rimrafSync
+
+var path = require("path")
+  , fs
+
+try {
+  // optional dependency
+  fs = require("../../graceful-fs/graceful-fs.js")
+} catch (er) {
+  fs = require("fs")
+}
+
+var lstat = "lstat"
+if (process.platform === "win32") {
+  // not reliable on windows prior to 0.7.9
+  var v = process.version.replace(/^v/, '').split(/\.|-/).map(Number)
+  if (v[0] === 0 && (v[1] < 7 || v[1] == 7 && v[2] < 9)) {
+    lstat = "stat"
+  }
+}
+if (!fs[lstat]) lstat = "stat"
+var lstatSync = lstat + "Sync"
+
+// for EMFILE handling
+var timeout = 0
+exports.EMFILE_MAX = 1000
+exports.BUSYTRIES_MAX = 3
+
+function rimraf (p, cb) {
+
+  if (!cb) throw new Error("No callback passed to rimraf()")
+
+  var busyTries = 0
+
+  rimraf_(p, function CB (er) {
+    if (er) {
+      if (er.code === "EBUSY" && busyTries < exports.BUSYTRIES_MAX) {
+        busyTries ++
+        var time = busyTries * 100
+        // try again, with the same exact callback as this one.
+        return setTimeout(function () {
+          rimraf_(p, CB)
+        }, time)
+      }
+
+      // this one won't happen if graceful-fs is used.
+      if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) {
+        return setTimeout(function () {
+          rimraf_(p, CB)
+        }, timeout ++)
+      }
+
+      // already gone
+      if (er.code === "ENOENT") er = null
+    }
+
+    timeout = 0
+    cb(er)
+  })
+}
+
+function rimraf_ (p, cb) {
+  fs[lstat](p, function (er, s) {
+    if (er) {
+      // already gone
+      if (er.code === "ENOENT") return cb()
+      // some other kind of error, permissions, etc.
+      return cb(er)
+    }
+
+    return rm_(p, s, false, cb)
+  })
+}
+
+
+var myGid = function myGid () {
+  var g = process.getuid && process.getgid()
+  myGid = function myGid () { return g }
+  return g
+}
+
+var myUid = function myUid () {
+  var u = process.getuid && process.getuid()
+  myUid = function myUid () { return u }
+  return u
+}
+
+
+function writable (s) {
+  var mode = s.mode || 0777
+    , uid = myUid()
+    , gid = myGid()
+  return (mode & 0002)
+      || (gid === s.gid && (mode & 0020))
+      || (uid === s.uid && (mode & 0200))
+}
+
+function rm_ (p, s, didWritableCheck, cb) {
+  if (!didWritableCheck && !writable(s)) {
+    // make file writable
+    // user/group/world, doesn't matter at this point
+    // since it's about to get nuked.
+    return fs.chmod(p, s.mode | 0222, function (er) {
+      if (er) return cb(er)
+      rm_(p, s, true, cb)
+    })
+  }
+
+  if (!s.isDirectory()) {
+    return fs.unlink(p, cb)
+  }
+
+  // directory
+  fs.readdir(p, function (er, files) {
+    if (er) return cb(er)
+    asyncForEach(files.map(function (f) {
+      return path.join(p, f)
+    }), function (file, cb) {
+      rimraf(file, cb)
+    }, function (er) {
+      if (er) return cb(er)
+      fs.rmdir(p, cb)
+    })
+  })
+}
+
+function asyncForEach (list, fn, cb) {
+  if (!list.length) cb()
+  var c = list.length
+    , errState = null
+  list.forEach(function (item, i, list) {
+    fn(item, function (er) {
+      if (errState) return
+      if (er) return cb(errState = er)
+      if (-- c === 0) return cb()
+    })
+  })
+}
+
+// this looks simpler, but it will fail with big directory trees,
+// or on slow stupid awful cygwin filesystems
+function rimrafSync (p) {
+  try {
+    var s = fs[lstatSync](p)
+  } catch (er) {
+    if (er.code === "ENOENT") return
+    throw er
+  }
+
+  if (!writable(s)) {
+    fs.chmodSync(p, s.mode | 0222)
+  }
+
+  if (!s.isDirectory()) return fs.unlinkSync(p)
+
+  fs.readdirSync(p).forEach(function (f) {
+    rimrafSync(path.join(p, f))
+  })
+  fs.rmdirSync(p)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/LICENSE	(revision 533)
@@ -0,0 +1,22 @@
+Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/README.md	(revision 533)
@@ -0,0 +1,19 @@
+                       __
+                      /\ \                                                         __
+     __  __    ___    \_\ \     __   _ __   ____    ___    ___   _ __    __       /\_\    ____
+    /\ \/\ \ /' _ `\  /'_  \  /'__`\/\  __\/ ,__\  / ___\ / __`\/\  __\/'__`\     \/\ \  /',__\
+    \ \ \_\ \/\ \/\ \/\ \ \ \/\  __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\  __/  __  \ \ \/\__, `\
+     \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
+      \/___/  \/_/\/_/\/__,_ /\/____/ \/_/ \/___/  \/____/\/___/  \/_/ \/____/\/_//\ \_\ \/___/
+                                                                                  \ \____/
+                                                                                   \/___/
+
+Underscore.js is a utility-belt library for JavaScript that provides
+support for the usual functional suspects (each, map, reduce, filter...)
+without extending any core JavaScript objects.
+
+For Docs, License, Tests, and pre-packed downloads, see:
+http://underscorejs.org
+
+Many thanks to our contributors:
+https://github.com/documentcloud/underscore/contributors
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/underscore.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/underscore.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/underscore.js	(revision 533)
@@ -0,0 +1,1226 @@
+//     Underscore.js 1.4.4
+//     http://underscorejs.org
+//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+//     Underscore may be freely distributed under the MIT license.
+
+(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 push             = ArrayProto.push,
+      slice            = ArrayProto.slice,
+      concat           = ArrayProto.concat,
+      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) {
+    if (obj instanceof _) return obj;
+    if (!(this instanceof _)) return new _(obj);
+    this._wrapped = 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.4.4';
+
+  // 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 (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);
+    });
+    return results;
+  };
+
+  var reduceError = 'Reduce of empty array with no initial value';
+
+  // **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(reduceError);
+    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 length = obj.length;
+    if (length !== +length) {
+      var keys = _.keys(obj);
+      length = keys.length;
+    }
+    each(obj, function(value, index, list) {
+      index = keys ? keys[--length] : --length;
+      if (!initial) {
+        memo = obj[index];
+        initial = true;
+      } else {
+        memo = iterator.call(context, memo, obj[index], index, list);
+      }
+    });
+    if (!initial) throw new TypeError(reduceError);
+    return memo;
+  };
+
+  // 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) {
+    return _.filter(obj, function(value, index, list) {
+      return !iterator.call(context, value, index, list);
+    }, context);
+  };
+
+  // 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) {
+    iterator || (iterator = _.identity);
+    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 the array or object contains a given value (using `===`).
+  // Aliased as `include`.
+  _.contains = _.include = function(obj, target) {
+    if (obj == null) return false;
+    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+    return any(obj, function(value) {
+      return value === target;
+    });
+  };
+
+  // Invoke a method (with arguments) on every item in a collection.
+  _.invoke = function(obj, method) {
+    var args = slice.call(arguments, 2);
+    var isFunc = _.isFunction(method);
+    return _.map(obj, function(value) {
+      return (isFunc ? method : 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]; });
+  };
+
+  // Convenience version of a common use case of `filter`: selecting only objects
+  // containing specific `key:value` pairs.
+  _.where = function(obj, attrs, first) {
+    if (_.isEmpty(attrs)) return first ? null : [];
+    return _[first ? 'find' : 'filter'](obj, function(value) {
+      for (var key in attrs) {
+        if (attrs[key] !== value[key]) return false;
+      }
+      return true;
+    });
+  };
+
+  // Convenience version of a common use case of `find`: getting the first object
+  // containing specific `key:value` pairs.
+  _.findWhere = function(obj, attrs) {
+    return _.where(obj, attrs, true);
+  };
+
+  // Return the maximum element or (element-based computation).
+  // Can't optimize arrays of integers longer than 65,535 elements.
+  // See: https://bugs.webkit.org/show_bug.cgi?id=80797
+  _.max = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+      return Math.max.apply(Math, obj);
+    }
+    if (!iterator && _.isEmpty(obj)) return -Infinity;
+    var result = {computed : -Infinity, value: -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) && obj[0] === +obj[0] && obj.length < 65535) {
+      return Math.min.apply(Math, obj);
+    }
+    if (!iterator && _.isEmpty(obj)) return Infinity;
+    var result = {computed : Infinity, value: 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 rand;
+    var index = 0;
+    var shuffled = [];
+    each(obj, function(value) {
+      rand = _.random(index++);
+      shuffled[index - 1] = shuffled[rand];
+      shuffled[rand] = value;
+    });
+    return shuffled;
+  };
+
+  // An internal function to generate lookup iterators.
+  var lookupIterator = function(value) {
+    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
+  };
+
+  // Sort the object's values by a criterion produced by an iterator.
+  _.sortBy = function(obj, value, context) {
+    var iterator = lookupIterator(value);
+    return _.pluck(_.map(obj, function(value, index, list) {
+      return {
+        value : value,
+        index : index,
+        criteria : iterator.call(context, value, index, list)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria;
+      var b = right.criteria;
+      if (a !== b) {
+        if (a > b || a === void 0) return 1;
+        if (a < b || b === void 0) return -1;
+      }
+      return left.index < right.index ? -1 : 1;
+    }), 'value');
+  };
+
+  // An internal function used for aggregate "group by" operations.
+  var group = function(obj, value, context, behavior) {
+    var result = {};
+    var iterator = lookupIterator(value || _.identity);
+    each(obj, function(value, index) {
+      var key = iterator.call(context, value, index, obj);
+      behavior(result, key, value);
+    });
+    return result;
+  };
+
+  // Groups the object's values by a criterion. Pass either a string attribute
+  // to group by, or a function that returns the criterion.
+  _.groupBy = function(obj, value, context) {
+    return group(obj, value, context, function(result, key, value) {
+      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
+    });
+  };
+
+  // Counts instances of an object that group by a certain criterion. Pass
+  // either a string attribute to count by, or a function that returns the
+  // criterion.
+  _.countBy = function(obj, value, context) {
+    return group(obj, value, context, function(result, key) {
+      if (!_.has(result, key)) result[key] = 0;
+      result[key]++;
+    });
+  };
+
+  // Use a comparator function to figure out the smallest index at which
+  // an object should be inserted so as to maintain order. Uses binary search.
+  _.sortedIndex = function(array, obj, iterator, context) {
+    iterator = iterator == null ? _.identity : lookupIterator(iterator);
+    var value = iterator.call(context, obj);
+    var low = 0, high = array.length;
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+    }
+    return low;
+  };
+
+  // Safely convert anything iterable into a real, live array.
+  _.toArray = function(obj) {
+    if (!obj) return [];
+    if (_.isArray(obj)) return slice.call(obj);
+    if (obj.length === +obj.length) return _.map(obj, _.identity);
+    return _.values(obj);
+  };
+
+  // Return the number of elements in an object.
+  _.size = function(obj) {
+    if (obj == null) return 0;
+    return (obj.length === +obj.length) ? obj.length : _.keys(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` and `take`. The **guard** check
+  // allows it to work with `_.map`.
+  _.first = _.head = _.take = function(array, n, guard) {
+    if (array == null) return void 0;
+    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+  };
+
+  // Returns everything but the last entry of the array. Especially 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 (array == null) return void 0;
+    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` and `drop`.
+  // Especially useful on the arguments object. Passing an **n** will return
+  // the rest N values in the array. The **guard**
+  // check allows it to work with `_.map`.
+  _.rest = _.tail = _.drop = function(array, n, guard) {
+    return slice.call(array, (n == null) || guard ? 1 : n);
+  };
+
+  // Trim out all falsy values from an array.
+  _.compact = function(array) {
+    return _.filter(array, _.identity);
+  };
+
+  // Internal implementation of a recursive `flatten` function.
+  var flatten = function(input, shallow, output) {
+    each(input, function(value) {
+      if (_.isArray(value)) {
+        shallow ? push.apply(output, value) : flatten(value, shallow, output);
+      } else {
+        output.push(value);
+      }
+    });
+    return output;
+  };
+
+  // Return a completely flattened version of an array.
+  _.flatten = function(array, shallow) {
+    return flatten(array, shallow, []);
+  };
+
+  // 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, context) {
+    if (_.isFunction(isSorted)) {
+      context = iterator;
+      iterator = isSorted;
+      isSorted = false;
+    }
+    var initial = iterator ? _.map(array, iterator, context) : array;
+    var results = [];
+    var seen = [];
+    each(initial, function(value, index) {
+      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
+        seen.push(value);
+        results.push(array[index]);
+      }
+    });
+    return results;
+  };
+
+  // Produce an array that contains the union: each distinct element from all of
+  // the passed-in arrays.
+  _.union = function() {
+    return _.uniq(concat.apply(ArrayProto, arguments));
+  };
+
+  // Produce an array that contains every item shared between all the
+  // passed-in arrays.
+  _.intersection = 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 = concat.apply(ArrayProto, slice.call(arguments, 1));
+    return _.filter(array, function(value){ return !_.contains(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;
+  };
+
+  // Converts lists into objects. Pass either a single array of `[key, value]`
+  // pairs, or two parallel arrays of the same length -- one of keys, and one of
+  // the corresponding values.
+  _.object = function(list, values) {
+    if (list == null) return {};
+    var result = {};
+    for (var i = 0, l = list.length; i < l; i++) {
+      if (values) {
+        result[list[i]] = values[i];
+      } else {
+        result[list[i][0]] = list[i][1];
+      }
+    }
+    return result;
+  };
+
+  // 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 = 0, l = array.length;
+    if (isSorted) {
+      if (typeof isSorted == 'number') {
+        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
+      } else {
+        i = _.sortedIndex(array, item);
+        return array[i] === item ? i : -1;
+      }
+    }
+    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
+    for (; i < l; i++) if (array[i] === item) return i;
+    return -1;
+  };
+
+  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+  _.lastIndexOf = function(array, item, from) {
+    if (array == null) return -1;
+    var hasIndex = from != null;
+    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
+      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
+    }
+    var i = (hasIndex ? from : array.length);
+    while (i--) if (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
+  // ------------------
+
+  // Create a function bound to a given object (assigning `this`, and arguments,
+  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+  // available.
+  _.bind = function(func, context) {
+    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+    var args = slice.call(arguments, 2);
+    return function() {
+      return func.apply(context, args.concat(slice.call(arguments)));
+    };
+  };
+
+  // Partially apply a function by creating a version that has had some of its
+  // arguments pre-filled, without changing its dynamic `this` context.
+  _.partial = function(func) {
+    var args = slice.call(arguments, 1);
+    return function() {
+      return func.apply(this, args.concat(slice.call(arguments)));
+    };
+  };
+
+  // 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(null, 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, result;
+    var previous = 0;
+    var later = function() {
+      previous = new Date;
+      timeout = null;
+      result = func.apply(context, args);
+    };
+    return function() {
+      var now = new Date;
+      var remaining = wait - (now - previous);
+      context = this;
+      args = arguments;
+      if (remaining <= 0) {
+        clearTimeout(timeout);
+        timeout = null;
+        previous = now;
+        result = func.apply(context, args);
+      } else if (!timeout) {
+        timeout = setTimeout(later, remaining);
+      }
+      return result;
+    };
+  };
+
+  // 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. If `immediate` is passed, trigger the function on the
+  // leading edge, instead of the trailing.
+  _.debounce = function(func, wait, immediate) {
+    var timeout, result;
+    return function() {
+      var context = this, args = arguments;
+      var later = function() {
+        timeout = null;
+        if (!immediate) result = func.apply(context, args);
+      };
+      var callNow = immediate && !timeout;
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+      if (callNow) result = func.apply(context, args);
+      return result;
+    };
+  };
+
+  // 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;
+      memo = func.apply(this, arguments);
+      func = null;
+      return memo;
+    };
+  };
+
+  // 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];
+      push.apply(args, arguments);
+      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) {
+    var values = [];
+    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
+    return values;
+  };
+
+  // Convert an object into a list of `[key, value]` pairs.
+  _.pairs = function(obj) {
+    var pairs = [];
+    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
+    return pairs;
+  };
+
+  // Invert the keys and values of an object. The values must be serializable.
+  _.invert = function(obj) {
+    var result = {};
+    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
+    return result;
+  };
+
+  // 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) {
+      if (source) {
+        for (var prop in source) {
+          obj[prop] = source[prop];
+        }
+      }
+    });
+    return obj;
+  };
+
+  // Return a copy of the object only containing the whitelisted properties.
+  _.pick = function(obj) {
+    var copy = {};
+    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+    each(keys, function(key) {
+      if (key in obj) copy[key] = obj[key];
+    });
+    return copy;
+  };
+
+   // Return a copy of the object without the blacklisted properties.
+  _.omit = function(obj) {
+    var copy = {};
+    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+    for (var key in obj) {
+      if (!_.contains(keys, key)) copy[key] = obj[key];
+    }
+    return copy;
+  };
+
+  // Fill in a given object with default properties.
+  _.defaults = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      if (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 for `isEqual`.
+  var eq = function(a, b, aStack, bStack) {
+    // 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 instanceof _) a = a._wrapped;
+    if (b instanceof _) b = b._wrapped;
+    // 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 = aStack.length;
+    while (length--) {
+      // Linear search. Performance is inversely proportional to the number of
+      // unique nested structures.
+      if (aStack[length] == a) return bStack[length] == b;
+    }
+    // Add the first object to the stack of traversed objects.
+    aStack.push(a);
+    bStack.push(b);
+    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--) {
+          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+        }
+      }
+    } else {
+      // Objects with different constructors are not equivalent, but `Object`s
+      // from different frames are.
+      var aCtor = a.constructor, bCtor = b.constructor;
+      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
+                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
+        return false;
+      }
+      // Deep compare objects.
+      for (var key in a) {
+        if (_.has(a, key)) {
+          // Count the expected number of properties.
+          size++;
+          // Deep compare each member.
+          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) 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.
+    aStack.pop();
+    bStack.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 (obj == null) return true;
+    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);
+  };
+
+  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
+  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+    _['is' + name] = function(obj) {
+      return toString.call(obj) == '[object ' + name + ']';
+    };
+  });
+
+  // Define a fallback version of the method in browsers (ahem, IE), where
+  // there isn't any inspectable "Arguments" type.
+  if (!_.isArguments(arguments)) {
+    _.isArguments = function(obj) {
+      return !!(obj && _.has(obj, 'callee'));
+    };
+  }
+
+  // Optimize `isFunction` if appropriate.
+  if (typeof (/./) !== 'function') {
+    _.isFunction = function(obj) {
+      return typeof obj === 'function';
+    };
+  }
+
+  // Is a given object a finite number?
+  _.isFinite = function(obj) {
+    return isFinite(obj) && !isNaN(parseFloat(obj));
+  };
+
+  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+  _.isNaN = function(obj) {
+    return _.isNumber(obj) && 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 equal to null?
+  _.isNull = function(obj) {
+    return obj === null;
+  };
+
+  // Is a given variable undefined?
+  _.isUndefined = function(obj) {
+    return obj === void 0;
+  };
+
+  // Shortcut function for checking if an object has a given property directly
+  // on itself (in other words, not on a prototype).
+  _.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) {
+    var accum = Array(n);
+    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
+    return accum;
+  };
+
+  // Return a random integer between min and max (inclusive).
+  _.random = function(min, max) {
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + Math.floor(Math.random() * (max - min + 1));
+  };
+
+  // List of HTML entities for escaping.
+  var entityMap = {
+    escape: {
+      '&': '&amp;',
+      '<': '&lt;',
+      '>': '&gt;',
+      '"': '&quot;',
+      "'": '&#x27;',
+      '/': '&#x2F;'
+    }
+  };
+  entityMap.unescape = _.invert(entityMap.escape);
+
+  // Regexes containing the keys and values listed immediately above.
+  var entityRegexes = {
+    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
+    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
+  };
+
+  // Functions for escaping and unescaping strings to/from HTML interpolation.
+  _.each(['escape', 'unescape'], function(method) {
+    _[method] = function(string) {
+      if (string == null) return '';
+      return ('' + string).replace(entityRegexes[method], function(match) {
+        return entityMap[method][match];
+      });
+    };
+  });
+
+  // If the value of the named property is a function then invoke it;
+  // otherwise, return it.
+  _.result = function(object, property) {
+    if (object == null) return null;
+    var value = object[property];
+    return _.isFunction(value) ? value.call(object) : value;
+  };
+
+  // Add your own custom functions to the Underscore object.
+  _.mixin = function(obj) {
+    each(_.functions(obj), function(name){
+      var func = _[name] = obj[name];
+      _.prototype[name] = function() {
+        var args = [this._wrapped];
+        push.apply(args, arguments);
+        return result.call(this, func.apply(_, args));
+      };
+    });
+  };
+
+  // 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 = /(.)^/;
+
+  // Certain characters need to be escaped so that they can be put into a
+  // string literal.
+  var escapes = {
+    "'":      "'",
+    '\\':     '\\',
+    '\r':     'r',
+    '\n':     'n',
+    '\t':     't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/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(text, data, settings) {
+    var render;
+    settings = _.defaults({}, settings, _.templateSettings);
+
+    // Combine delimiters into one regular expression via alternation.
+    var matcher = new RegExp([
+      (settings.escape || noMatch).source,
+      (settings.interpolate || noMatch).source,
+      (settings.evaluate || noMatch).source
+    ].join('|') + '|$', 'g');
+
+    // Compile the template source, escaping string literals appropriately.
+    var index = 0;
+    var source = "__p+='";
+    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+      source += text.slice(index, offset)
+        .replace(escaper, function(match) { return '\\' + escapes[match]; });
+
+      if (escape) {
+        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+      }
+      if (interpolate) {
+        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+      }
+      if (evaluate) {
+        source += "';\n" + evaluate + "\n__p+='";
+      }
+      index = offset + match.length;
+      return match;
+    });
+    source += "';\n";
+
+    // If a variable is not specified, place data values in local scope.
+    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+    source = "var __t,__p='',__j=Array.prototype.join," +
+      "print=function(){__p+=__j.call(arguments,'');};\n" +
+      source + "return __p;\n";
+
+    try {
+      render = new Function(settings.variable || 'obj', '_', source);
+    } catch (e) {
+      e.source = source;
+      throw e;
+    }
+
+    if (data) return render(data, _);
+    var template = function(data) {
+      return render.call(this, data, _);
+    };
+
+    // Provide the compiled function source as a convenience for precompilation.
+    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
+
+    return template;
+  };
+
+  // Add a "chain" function, which will delegate to the wrapper.
+  _.chain = function(obj) {
+    return _(obj).chain();
+  };
+
+  // OOP
+  // ---------------
+  // 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.
+
+  // Helper function to continue chaining intermediate results.
+  var result = function(obj) {
+    return this._chain ? _(obj).chain() : obj;
+  };
+
+  // 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];
+    _.prototype[name] = function() {
+      var obj = this._wrapped;
+      method.apply(obj, arguments);
+      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
+      return result.call(this, obj);
+    };
+  });
+
+  // Add all accessor Array functions to the wrapper.
+  each(['concat', 'join', 'slice'], function(name) {
+    var method = ArrayProto[name];
+    _.prototype[name] = function() {
+      return result.call(this, method.apply(this._wrapped, arguments));
+    };
+  });
+
+  _.extend(_.prototype, {
+
+    // Start chaining a wrapped Underscore object.
+    chain: function() {
+      this._chain = true;
+      return this;
+    },
+
+    // Extracts the result from a wrapped and chained object.
+    value: function() {
+      return this._wrapped;
+    }
+
+  });
+
+}).call(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+node_modules
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE	(revision 533)
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+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 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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md	(revision 533)
@@ -0,0 +1,218 @@
+# minimatch
+
+A minimal matching utility.
+
+[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)
+
+
+This is the matching library used internally by npm.
+
+Eventually, it will replace the C binding in node-glob.
+
+It works by converting glob expressions into JavaScript `RegExp`
+objects.
+
+## Usage
+
+```javascript
+var minimatch = require("minimatch")
+
+minimatch("bar.foo", "*.foo") // true!
+minimatch("bar.foo", "*.bar") // false!
+minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
+```
+
+## Features
+
+Supports these glob features:
+
+* Brace Expansion
+* Extended glob matching
+* "Globstar" `**` matching
+
+See:
+
+* `man sh`
+* `man bash`
+* `man 3 fnmatch`
+* `man 5 gitignore`
+
+## Minimatch Class
+
+Create a minimatch object by instanting the `minimatch.Minimatch` class.
+
+```javascript
+var Minimatch = require("minimatch").Minimatch
+var mm = new Minimatch(pattern, options)
+```
+
+### Properties
+
+* `pattern` The original pattern the minimatch object represents.
+* `options` The options supplied to the constructor.
+* `set` A 2-dimensional array of regexp or string expressions.
+  Each row in the
+  array corresponds to a brace-expanded pattern.  Each item in the row
+  corresponds to a single path-part.  For example, the pattern
+  `{a,b/c}/d` would expand to a set of patterns like:
+
+        [ [ a, d ]
+        , [ b, c, d ] ]
+
+    If a portion of the pattern doesn't have any "magic" in it
+    (that is, it's something like `"foo"` rather than `fo*o?`), then it
+    will be left as a string rather than converted to a regular
+    expression.
+
+* `regexp` Created by the `makeRe` method.  A single regular expression
+  expressing the entire pattern.  This is useful in cases where you wish
+  to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
+* `negate` True if the pattern is negated.
+* `comment` True if the pattern is a comment.
+* `empty` True if the pattern is `""`.
+
+### Methods
+
+* `makeRe` Generate the `regexp` member if necessary, and return it.
+  Will return `false` if the pattern is invalid.
+* `match(fname)` Return true if the filename matches the pattern, or
+  false otherwise.
+* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
+  filename, and match it against a single row in the `regExpSet`.  This
+  method is mainly for internal use, but is exposed so that it can be
+  used by a glob-walker that needs to avoid excessive filesystem calls.
+
+All other methods are internal, and will be called as necessary.
+
+## Functions
+
+The top-level exported function has a `cache` property, which is an LRU
+cache set to store 100 items.  So, calling these methods repeatedly
+with the same pattern and options will use the same Minimatch object,
+saving the cost of parsing it multiple times.
+
+### minimatch(path, pattern, options)
+
+Main export.  Tests a path against the pattern using the options.
+
+```javascript
+var isJS = minimatch(file, "*.js", { matchBase: true })
+```
+
+### minimatch.filter(pattern, options)
+
+Returns a function that tests its
+supplied argument, suitable for use with `Array.filter`.  Example:
+
+```javascript
+var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
+```
+
+### minimatch.match(list, pattern, options)
+
+Match against the list of
+files, in the style of fnmatch or glob.  If nothing is matched, and
+options.nonull is set, then return a list containing the pattern itself.
+
+```javascript
+var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
+```
+
+### minimatch.makeRe(pattern, options)
+
+Make a regular expression object from the pattern.
+
+## Options
+
+All options are `false` by default.
+
+### debug
+
+Dump a ton of stuff to stderr.
+
+### nobrace
+
+Do not expand `{a,b}` and `{1..3}` brace sets.
+
+### noglobstar
+
+Disable `**` matching against multiple folder names.
+
+### dot
+
+Allow patterns to match filenames starting with a period, even if
+the pattern does not explicitly have a period in that spot.
+
+Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
+is set.
+
+### noext
+
+Disable "extglob" style patterns like `+(a|b)`.
+
+### nocase
+
+Perform a case-insensitive match.
+
+### nonull
+
+When a match is not found by `minimatch.match`, return a list containing
+the pattern itself.  When set, an empty list is returned if there are
+no matches.
+
+### matchBase
+
+If set, then patterns without slashes will be matched
+against the basename of the path if it contains slashes.  For example,
+`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
+
+### nocomment
+
+Suppress the behavior of treating `#` at the start of a pattern as a
+comment.
+
+### nonegate
+
+Suppress the behavior of treating a leading `!` character as negation.
+
+### flipNegate
+
+Returns from negate expressions the same as if they were not negated.
+(Ie, true on a hit, false on a miss.)
+
+
+## Comparisons to other fnmatch/glob implementations
+
+While strict compliance with the existing standards is a worthwhile
+goal, some discrepancies exist between minimatch and other
+implementations, and are intentional.
+
+If the pattern starts with a `!` character, then it is negated.  Set the
+`nonegate` flag to suppress this behavior, and treat leading `!`
+characters normally.  This is perhaps relevant if you wish to start the
+pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
+characters at the start of a pattern will negate the pattern multiple
+times.
+
+If a pattern starts with `#`, then it is treated as a comment, and
+will not match anything.  Use `\#` to match a literal `#` at the
+start of a line, or set the `nocomment` flag to suppress this behavior.
+
+The double-star character `**` is supported by default, unless the
+`noglobstar` flag is set.  This is supported in the manner of bsdglob
+and bash 4.1, where `**` only has special significance if it is the only
+thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
+`a/**b` will not.
+
+If an escaped pattern has no matches, and the `nonull` flag is set,
+then minimatch.match returns the pattern as-provided, rather than
+interpreting the character escapes.  For example,
+`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
+`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
+that it does not resolve escaped pattern characters.
+
+If brace expansion is not disabled, then it is performed before any
+other interpretation of the glob pattern.  Thus, a pattern like
+`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
+**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
+checked for validity.  Since those two are valid, matching proceeds.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js	(revision 533)
@@ -0,0 +1,1055 @@
+;(function (require, exports, module, platform) {
+
+if (module) module.exports = minimatch
+else exports.minimatch = minimatch
+
+if (!require) {
+  require = function (id) {
+    switch (id) {
+      case "sigmund": return function sigmund (obj) {
+        return JSON.stringify(obj)
+      }
+      case "path": return { basename: function (f) {
+        f = f.split(/[\/\\]/)
+        var e = f.pop()
+        if (!e) e = f.pop()
+        return e
+      }}
+      case "lru-cache": return function LRUCache () {
+        // not quite an LRU, but still space-limited.
+        var cache = {}
+        var cnt = 0
+        this.set = function (k, v) {
+          cnt ++
+          if (cnt >= 100) cache = {}
+          cache[k] = v
+        }
+        this.get = function (k) { return cache[k] }
+      }
+    }
+  }
+}
+
+minimatch.Minimatch = Minimatch
+
+var LRU = require("lru-cache")
+  , cache = minimatch.cache = new LRU({max: 100})
+  , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
+  , sigmund = require("sigmund")
+
+var path = require("path")
+  // any single thing other than /
+  // don't need to escape / when using new RegExp()
+  , qmark = "[^/]"
+
+  // * => any number of characters
+  , star = qmark + "*?"
+
+  // ** when dots are allowed.  Anything goes, except .. and .
+  // not (^ or / followed by one or two dots followed by $ or /),
+  // followed by anything, any number of times.
+  , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?"
+
+  // not a ^ or / followed by a dot,
+  // followed by anything, any number of times.
+  , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?"
+
+  // characters that need to be escaped in RegExp.
+  , reSpecials = charSet("().*{}+?[]^$\\!")
+
+// "abc" -> { a:true, b:true, c:true }
+function charSet (s) {
+  return s.split("").reduce(function (set, c) {
+    set[c] = true
+    return set
+  }, {})
+}
+
+// normalizes slashes.
+var slashSplit = /\/+/
+
+minimatch.filter = filter
+function filter (pattern, options) {
+  options = options || {}
+  return function (p, i, list) {
+    return minimatch(p, pattern, options)
+  }
+}
+
+function ext (a, b) {
+  a = a || {}
+  b = b || {}
+  var t = {}
+  Object.keys(b).forEach(function (k) {
+    t[k] = b[k]
+  })
+  Object.keys(a).forEach(function (k) {
+    t[k] = a[k]
+  })
+  return t
+}
+
+minimatch.defaults = function (def) {
+  if (!def || !Object.keys(def).length) return minimatch
+
+  var orig = minimatch
+
+  var m = function minimatch (p, pattern, options) {
+    return orig.minimatch(p, pattern, ext(def, options))
+  }
+
+  m.Minimatch = function Minimatch (pattern, options) {
+    return new orig.Minimatch(pattern, ext(def, options))
+  }
+
+  return m
+}
+
+Minimatch.defaults = function (def) {
+  if (!def || !Object.keys(def).length) return Minimatch
+  return minimatch.defaults(def).Minimatch
+}
+
+
+function minimatch (p, pattern, options) {
+  if (typeof pattern !== "string") {
+    throw new TypeError("glob pattern string required")
+  }
+
+  if (!options) options = {}
+
+  // shortcut: comments match nothing.
+  if (!options.nocomment && pattern.charAt(0) === "#") {
+    return false
+  }
+
+  // "" only matches ""
+  if (pattern.trim() === "") return p === ""
+
+  return new Minimatch(pattern, options).match(p)
+}
+
+function Minimatch (pattern, options) {
+  if (!(this instanceof Minimatch)) {
+    return new Minimatch(pattern, options, cache)
+  }
+
+  if (typeof pattern !== "string") {
+    throw new TypeError("glob pattern string required")
+  }
+
+  if (!options) options = {}
+  pattern = pattern.trim()
+
+  // windows: need to use /, not \
+  // On other platforms, \ is a valid (albeit bad) filename char.
+  if (platform === "win32") {
+    pattern = pattern.split("\\").join("/")
+  }
+
+  // lru storage.
+  // these things aren't particularly big, but walking down the string
+  // and turning it into a regexp can get pretty costly.
+  var cacheKey = pattern + "\n" + sigmund(options)
+  var cached = minimatch.cache.get(cacheKey)
+  if (cached) return cached
+  minimatch.cache.set(cacheKey, this)
+
+  this.options = options
+  this.set = []
+  this.pattern = pattern
+  this.regexp = null
+  this.negate = false
+  this.comment = false
+  this.empty = false
+
+  // make the set of regexps etc.
+  this.make()
+}
+
+Minimatch.prototype.debug = function() {}
+
+Minimatch.prototype.make = make
+function make () {
+  // don't do it more than once.
+  if (this._made) return
+
+  var pattern = this.pattern
+  var options = this.options
+
+  // empty patterns and comments match nothing.
+  if (!options.nocomment && pattern.charAt(0) === "#") {
+    this.comment = true
+    return
+  }
+  if (!pattern) {
+    this.empty = true
+    return
+  }
+
+  // step 1: figure out negation, etc.
+  this.parseNegate()
+
+  // step 2: expand braces
+  var set = this.globSet = this.braceExpand()
+
+  if (options.debug) this.debug = console.error
+
+  this.debug(this.pattern, set)
+
+  // step 3: now we have a set, so turn each one into a series of path-portion
+  // matching patterns.
+  // These will be regexps, except in the case of "**", which is
+  // set to the GLOBSTAR object for globstar behavior,
+  // and will not contain any / characters
+  set = this.globParts = set.map(function (s) {
+    return s.split(slashSplit)
+  })
+
+  this.debug(this.pattern, set)
+
+  // glob --> regexps
+  set = set.map(function (s, si, set) {
+    return s.map(this.parse, this)
+  }, this)
+
+  this.debug(this.pattern, set)
+
+  // filter out everything that didn't compile properly.
+  set = set.filter(function (s) {
+    return -1 === s.indexOf(false)
+  })
+
+  this.debug(this.pattern, set)
+
+  this.set = set
+}
+
+Minimatch.prototype.parseNegate = parseNegate
+function parseNegate () {
+  var pattern = this.pattern
+    , negate = false
+    , options = this.options
+    , negateOffset = 0
+
+  if (options.nonegate) return
+
+  for ( var i = 0, l = pattern.length
+      ; i < l && pattern.charAt(i) === "!"
+      ; i ++) {
+    negate = !negate
+    negateOffset ++
+  }
+
+  if (negateOffset) this.pattern = pattern.substr(negateOffset)
+  this.negate = negate
+}
+
+// Brace expansion:
+// a{b,c}d -> abd acd
+// a{b,}c -> abc ac
+// a{0..3}d -> a0d a1d a2d a3d
+// a{b,c{d,e}f}g -> abg acdfg acefg
+// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
+//
+// Invalid sets are not expanded.
+// a{2..}b -> a{2..}b
+// a{b}c -> a{b}c
+minimatch.braceExpand = function (pattern, options) {
+  return new Minimatch(pattern, options).braceExpand()
+}
+
+Minimatch.prototype.braceExpand = braceExpand
+function braceExpand (pattern, options) {
+  options = options || this.options
+  pattern = typeof pattern === "undefined"
+    ? this.pattern : pattern
+
+  if (typeof pattern === "undefined") {
+    throw new Error("undefined pattern")
+  }
+
+  if (options.nobrace ||
+      !pattern.match(/\{.*\}/)) {
+    // shortcut. no need to expand.
+    return [pattern]
+  }
+
+  var escaping = false
+
+  // examples and comments refer to this crazy pattern:
+  // a{b,c{d,e},{f,g}h}x{y,z}
+  // expected:
+  // abxy
+  // abxz
+  // acdxy
+  // acdxz
+  // acexy
+  // acexz
+  // afhxy
+  // afhxz
+  // aghxy
+  // aghxz
+
+  // everything before the first \{ is just a prefix.
+  // So, we pluck that off, and work with the rest,
+  // and then prepend it to everything we find.
+  if (pattern.charAt(0) !== "{") {
+    this.debug(pattern)
+    var prefix = null
+    for (var i = 0, l = pattern.length; i < l; i ++) {
+      var c = pattern.charAt(i)
+      this.debug(i, c)
+      if (c === "\\") {
+        escaping = !escaping
+      } else if (c === "{" && !escaping) {
+        prefix = pattern.substr(0, i)
+        break
+      }
+    }
+
+    // actually no sets, all { were escaped.
+    if (prefix === null) {
+      this.debug("no sets")
+      return [pattern]
+    }
+
+   var tail = braceExpand.call(this, pattern.substr(i), options)
+    return tail.map(function (t) {
+      return prefix + t
+    })
+  }
+
+  // now we have something like:
+  // {b,c{d,e},{f,g}h}x{y,z}
+  // walk through the set, expanding each part, until
+  // the set ends.  then, we'll expand the suffix.
+  // If the set only has a single member, then'll put the {} back
+
+  // first, handle numeric sets, since they're easier
+  var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/)
+  if (numset) {
+    this.debug("numset", numset[1], numset[2])
+    var suf = braceExpand.call(this, pattern.substr(numset[0].length), options)
+      , start = +numset[1]
+      , end = +numset[2]
+      , inc = start > end ? -1 : 1
+      , set = []
+    for (var i = start; i != (end + inc); i += inc) {
+      // append all the suffixes
+      for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
+        set.push(i + suf[ii])
+      }
+    }
+    return set
+  }
+
+  // ok, walk through the set
+  // We hope, somewhat optimistically, that there
+  // will be a } at the end.
+  // If the closing brace isn't found, then the pattern is
+  // interpreted as braceExpand("\\" + pattern) so that
+  // the leading \{ will be interpreted literally.
+  var i = 1 // skip the \{
+    , depth = 1
+    , set = []
+    , member = ""
+    , sawEnd = false
+    , escaping = false
+
+  function addMember () {
+    set.push(member)
+    member = ""
+  }
+
+  this.debug("Entering for")
+  FOR: for (i = 1, l = pattern.length; i < l; i ++) {
+    var c = pattern.charAt(i)
+    this.debug("", i, c)
+
+    if (escaping) {
+      escaping = false
+      member += "\\" + c
+    } else {
+      switch (c) {
+        case "\\":
+          escaping = true
+          continue
+
+        case "{":
+          depth ++
+          member += "{"
+          continue
+
+        case "}":
+          depth --
+          // if this closes the actual set, then we're done
+          if (depth === 0) {
+            addMember()
+            // pluck off the close-brace
+            i ++
+            break FOR
+          } else {
+            member += c
+            continue
+          }
+
+        case ",":
+          if (depth === 1) {
+            addMember()
+          } else {
+            member += c
+          }
+          continue
+
+        default:
+          member += c
+          continue
+      } // switch
+    } // else
+  } // for
+
+  // now we've either finished the set, and the suffix is
+  // pattern.substr(i), or we have *not* closed the set,
+  // and need to escape the leading brace
+  if (depth !== 0) {
+    this.debug("didn't close", pattern)
+    return braceExpand.call(this, "\\" + pattern, options)
+  }
+
+  // x{y,z} -> ["xy", "xz"]
+  this.debug("set", set)
+  this.debug("suffix", pattern.substr(i))
+  var suf = braceExpand.call(this, pattern.substr(i), options)
+  // ["b", "c{d,e}","{f,g}h"] ->
+  //   [["b"], ["cd", "ce"], ["fh", "gh"]]
+  var addBraces = set.length === 1
+  this.debug("set pre-expanded", set)
+  set = set.map(function (p) {
+    return braceExpand.call(this, p, options)
+  }, this)
+  this.debug("set expanded", set)
+
+
+  // [["b"], ["cd", "ce"], ["fh", "gh"]] ->
+  //   ["b", "cd", "ce", "fh", "gh"]
+  set = set.reduce(function (l, r) {
+    return l.concat(r)
+  })
+
+  if (addBraces) {
+    set = set.map(function (s) {
+      return "{" + s + "}"
+    })
+  }
+
+  // now attach the suffixes.
+  var ret = []
+  for (var i = 0, l = set.length; i < l; i ++) {
+    for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
+      ret.push(set[i] + suf[ii])
+    }
+  }
+  return ret
+}
+
+// parse a component of the expanded set.
+// At this point, no pattern may contain "/" in it
+// so we're going to return a 2d array, where each entry is the full
+// pattern, split on '/', and then turned into a regular expression.
+// A regexp is made at the end which joins each array with an
+// escaped /, and another full one which joins each regexp with |.
+//
+// Following the lead of Bash 4.1, note that "**" only has special meaning
+// when it is the *only* thing in a path portion.  Otherwise, any series
+// of * is equivalent to a single *.  Globstar behavior is enabled by
+// default, and can be disabled by setting options.noglobstar.
+Minimatch.prototype.parse = parse
+var SUBPARSE = {}
+function parse (pattern, isSub) {
+  var options = this.options
+
+  // shortcuts
+  if (!options.noglobstar && pattern === "**") return GLOBSTAR
+  if (pattern === "") return ""
+
+  var re = ""
+    , hasMagic = !!options.nocase
+    , escaping = false
+    // ? => one single character
+    , patternListStack = []
+    , plType
+    , stateChar
+    , inClass = false
+    , reClassStart = -1
+    , classStart = -1
+    // . and .. never match anything that doesn't start with .,
+    // even when options.dot is set.
+    , patternStart = pattern.charAt(0) === "." ? "" // anything
+      // not (start or / followed by . or .. followed by / or end)
+      : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))"
+      : "(?!\\.)"
+    , self = this
+
+  function clearStateChar () {
+    if (stateChar) {
+      // we had some state-tracking character
+      // that wasn't consumed by this pass.
+      switch (stateChar) {
+        case "*":
+          re += star
+          hasMagic = true
+          break
+        case "?":
+          re += qmark
+          hasMagic = true
+          break
+        default:
+          re += "\\"+stateChar
+          break
+      }
+      self.debug('clearStateChar %j %j', stateChar, re)
+      stateChar = false
+    }
+  }
+
+  for ( var i = 0, len = pattern.length, c
+      ; (i < len) && (c = pattern.charAt(i))
+      ; i ++ ) {
+
+    this.debug("%s\t%s %s %j", pattern, i, re, c)
+
+    // skip over any that are escaped.
+    if (escaping && reSpecials[c]) {
+      re += "\\" + c
+      escaping = false
+      continue
+    }
+
+    SWITCH: switch (c) {
+      case "/":
+        // completely not allowed, even escaped.
+        // Should already be path-split by now.
+        return false
+
+      case "\\":
+        clearStateChar()
+        escaping = true
+        continue
+
+      // the various stateChar values
+      // for the "extglob" stuff.
+      case "?":
+      case "*":
+      case "+":
+      case "@":
+      case "!":
+        this.debug("%s\t%s %s %j <-- stateChar", pattern, i, re, c)
+
+        // all of those are literals inside a class, except that
+        // the glob [!a] means [^a] in regexp
+        if (inClass) {
+          this.debug('  in class')
+          if (c === "!" && i === classStart + 1) c = "^"
+          re += c
+          continue
+        }
+
+        // if we already have a stateChar, then it means
+        // that there was something like ** or +? in there.
+        // Handle the stateChar, then proceed with this one.
+        self.debug('call clearStateChar %j', stateChar)
+        clearStateChar()
+        stateChar = c
+        // if extglob is disabled, then +(asdf|foo) isn't a thing.
+        // just clear the statechar *now*, rather than even diving into
+        // the patternList stuff.
+        if (options.noext) clearStateChar()
+        continue
+
+      case "(":
+        if (inClass) {
+          re += "("
+          continue
+        }
+
+        if (!stateChar) {
+          re += "\\("
+          continue
+        }
+
+        plType = stateChar
+        patternListStack.push({ type: plType
+                              , start: i - 1
+                              , reStart: re.length })
+        // negation is (?:(?!js)[^/]*)
+        re += stateChar === "!" ? "(?:(?!" : "(?:"
+        this.debug('plType %j %j', stateChar, re)
+        stateChar = false
+        continue
+
+      case ")":
+        if (inClass || !patternListStack.length) {
+          re += "\\)"
+          continue
+        }
+
+        clearStateChar()
+        hasMagic = true
+        re += ")"
+        plType = patternListStack.pop().type
+        // negation is (?:(?!js)[^/]*)
+        // The others are (?:<pattern>)<type>
+        switch (plType) {
+          case "!":
+            re += "[^/]*?)"
+            break
+          case "?":
+          case "+":
+          case "*": re += plType
+          case "@": break // the default anyway
+        }
+        continue
+
+      case "|":
+        if (inClass || !patternListStack.length || escaping) {
+          re += "\\|"
+          escaping = false
+          continue
+        }
+
+        clearStateChar()
+        re += "|"
+        continue
+
+      // these are mostly the same in regexp and glob
+      case "[":
+        // swallow any state-tracking char before the [
+        clearStateChar()
+
+        if (inClass) {
+          re += "\\" + c
+          continue
+        }
+
+        inClass = true
+        classStart = i
+        reClassStart = re.length
+        re += c
+        continue
+
+      case "]":
+        //  a right bracket shall lose its special
+        //  meaning and represent itself in
+        //  a bracket expression if it occurs
+        //  first in the list.  -- POSIX.2 2.8.3.2
+        if (i === classStart + 1 || !inClass) {
+          re += "\\" + c
+          escaping = false
+          continue
+        }
+
+        // finish up the class.
+        hasMagic = true
+        inClass = false
+        re += c
+        continue
+
+      default:
+        // swallow any state char that wasn't consumed
+        clearStateChar()
+
+        if (escaping) {
+          // no need
+          escaping = false
+        } else if (reSpecials[c]
+                   && !(c === "^" && inClass)) {
+          re += "\\"
+        }
+
+        re += c
+
+    } // switch
+  } // for
+
+
+  // handle the case where we left a class open.
+  // "[abc" is valid, equivalent to "\[abc"
+  if (inClass) {
+    // split where the last [ was, and escape it
+    // this is a huge pita.  We now have to re-walk
+    // the contents of the would-be class to re-translate
+    // any characters that were passed through as-is
+    var cs = pattern.substr(classStart + 1)
+      , sp = this.parse(cs, SUBPARSE)
+    re = re.substr(0, reClassStart) + "\\[" + sp[0]
+    hasMagic = hasMagic || sp[1]
+  }
+
+  // handle the case where we had a +( thing at the *end*
+  // of the pattern.
+  // each pattern list stack adds 3 chars, and we need to go through
+  // and escape any | chars that were passed through as-is for the regexp.
+  // Go through and escape them, taking care not to double-escape any
+  // | chars that were already escaped.
+  var pl
+  while (pl = patternListStack.pop()) {
+    var tail = re.slice(pl.reStart + 3)
+    // maybe some even number of \, then maybe 1 \, followed by a |
+    tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
+      if (!$2) {
+        // the | isn't already escaped, so escape it.
+        $2 = "\\"
+      }
+
+      // need to escape all those slashes *again*, without escaping the
+      // one that we need for escaping the | character.  As it works out,
+      // escaping an even number of slashes can be done by simply repeating
+      // it exactly after itself.  That's why this trick works.
+      //
+      // I am sorry that you have to see this.
+      return $1 + $1 + $2 + "|"
+    })
+
+    this.debug("tail=%j\n   %s", tail, tail)
+    var t = pl.type === "*" ? star
+          : pl.type === "?" ? qmark
+          : "\\" + pl.type
+
+    hasMagic = true
+    re = re.slice(0, pl.reStart)
+       + t + "\\("
+       + tail
+  }
+
+  // handle trailing things that only matter at the very end.
+  clearStateChar()
+  if (escaping) {
+    // trailing \\
+    re += "\\\\"
+  }
+
+  // only need to apply the nodot start if the re starts with
+  // something that could conceivably capture a dot
+  var addPatternStart = false
+  switch (re.charAt(0)) {
+    case ".":
+    case "[":
+    case "(": addPatternStart = true
+  }
+
+  // if the re is not "" at this point, then we need to make sure
+  // it doesn't match against an empty path part.
+  // Otherwise a/* will match a/, which it should not.
+  if (re !== "" && hasMagic) re = "(?=.)" + re
+
+  if (addPatternStart) re = patternStart + re
+
+  // parsing just a piece of a larger pattern.
+  if (isSub === SUBPARSE) {
+    return [ re, hasMagic ]
+  }
+
+  // skip the regexp for non-magical patterns
+  // unescape anything in it, though, so that it'll be
+  // an exact match against a file etc.
+  if (!hasMagic) {
+    return globUnescape(pattern)
+  }
+
+  var flags = options.nocase ? "i" : ""
+    , regExp = new RegExp("^" + re + "$", flags)
+
+  regExp._glob = pattern
+  regExp._src = re
+
+  return regExp
+}
+
+minimatch.makeRe = function (pattern, options) {
+  return new Minimatch(pattern, options || {}).makeRe()
+}
+
+Minimatch.prototype.makeRe = makeRe
+function makeRe () {
+  if (this.regexp || this.regexp === false) return this.regexp
+
+  // at this point, this.set is a 2d array of partial
+  // pattern strings, or "**".
+  //
+  // It's better to use .match().  This function shouldn't
+  // be used, really, but it's pretty convenient sometimes,
+  // when you just want to work with a regex.
+  var set = this.set
+
+  if (!set.length) return this.regexp = false
+  var options = this.options
+
+  var twoStar = options.noglobstar ? star
+      : options.dot ? twoStarDot
+      : twoStarNoDot
+    , flags = options.nocase ? "i" : ""
+
+  var re = set.map(function (pattern) {
+    return pattern.map(function (p) {
+      return (p === GLOBSTAR) ? twoStar
+           : (typeof p === "string") ? regExpEscape(p)
+           : p._src
+    }).join("\\\/")
+  }).join("|")
+
+  // must match entire pattern
+  // ending in a * or ** will make it less strict.
+  re = "^(?:" + re + ")$"
+
+  // can match anything, as long as it's not this.
+  if (this.negate) re = "^(?!" + re + ").*$"
+
+  try {
+    return this.regexp = new RegExp(re, flags)
+  } catch (ex) {
+    return this.regexp = false
+  }
+}
+
+minimatch.match = function (list, pattern, options) {
+  var mm = new Minimatch(pattern, options)
+  list = list.filter(function (f) {
+    return mm.match(f)
+  })
+  if (options.nonull && !list.length) {
+    list.push(pattern)
+  }
+  return list
+}
+
+Minimatch.prototype.match = match
+function match (f, partial) {
+  this.debug("match", f, this.pattern)
+  // short-circuit in the case of busted things.
+  // comments, etc.
+  if (this.comment) return false
+  if (this.empty) return f === ""
+
+  if (f === "/" && partial) return true
+
+  var options = this.options
+
+  // windows: need to use /, not \
+  // On other platforms, \ is a valid (albeit bad) filename char.
+  if (platform === "win32") {
+    f = f.split("\\").join("/")
+  }
+
+  // treat the test path as a set of pathparts.
+  f = f.split(slashSplit)
+  this.debug(this.pattern, "split", f)
+
+  // just ONE of the pattern sets in this.set needs to match
+  // in order for it to be valid.  If negating, then just one
+  // match means that we have failed.
+  // Either way, return on the first hit.
+
+  var set = this.set
+  this.debug(this.pattern, "set", set)
+
+  var splitFile = path.basename(f.join("/")).split("/")
+
+  for (var i = 0, l = set.length; i < l; i ++) {
+    var pattern = set[i], file = f
+    if (options.matchBase && pattern.length === 1) {
+      file = splitFile
+    }
+    var hit = this.matchOne(file, pattern, partial)
+    if (hit) {
+      if (options.flipNegate) return true
+      return !this.negate
+    }
+  }
+
+  // didn't get any hits.  this is success if it's a negative
+  // pattern, failure otherwise.
+  if (options.flipNegate) return false
+  return this.negate
+}
+
+// set partial to true to test if, for example,
+// "/a/b" matches the start of "/*/b/*/d"
+// Partial means, if you run out of file before you run
+// out of pattern, then that's fine, as long as all
+// the parts match.
+Minimatch.prototype.matchOne = function (file, pattern, partial) {
+  var options = this.options
+
+  this.debug("matchOne",
+              { "this": this
+              , file: file
+              , pattern: pattern })
+
+  this.debug("matchOne", file.length, pattern.length)
+
+  for ( var fi = 0
+          , pi = 0
+          , fl = file.length
+          , pl = pattern.length
+      ; (fi < fl) && (pi < pl)
+      ; fi ++, pi ++ ) {
+
+    this.debug("matchOne loop")
+    var p = pattern[pi]
+      , f = file[fi]
+
+    this.debug(pattern, p, f)
+
+    // should be impossible.
+    // some invalid regexp stuff in the set.
+    if (p === false) return false
+
+    if (p === GLOBSTAR) {
+      this.debug('GLOBSTAR', [pattern, p, f])
+
+      // "**"
+      // a/**/b/**/c would match the following:
+      // a/b/x/y/z/c
+      // a/x/y/z/b/c
+      // a/b/x/b/x/c
+      // a/b/c
+      // To do this, take the rest of the pattern after
+      // the **, and see if it would match the file remainder.
+      // If so, return success.
+      // If not, the ** "swallows" a segment, and try again.
+      // This is recursively awful.
+      //
+      // a/**/b/**/c matching a/b/x/y/z/c
+      // - a matches a
+      // - doublestar
+      //   - matchOne(b/x/y/z/c, b/**/c)
+      //     - b matches b
+      //     - doublestar
+      //       - matchOne(x/y/z/c, c) -> no
+      //       - matchOne(y/z/c, c) -> no
+      //       - matchOne(z/c, c) -> no
+      //       - matchOne(c, c) yes, hit
+      var fr = fi
+        , pr = pi + 1
+      if (pr === pl) {
+        this.debug('** at the end')
+        // a ** at the end will just swallow the rest.
+        // We have found a match.
+        // however, it will not swallow /.x, unless
+        // options.dot is set.
+        // . and .. are *never* matched by **, for explosively
+        // exponential reasons.
+        for ( ; fi < fl; fi ++) {
+          if (file[fi] === "." || file[fi] === ".." ||
+              (!options.dot && file[fi].charAt(0) === ".")) return false
+        }
+        return true
+      }
+
+      // ok, let's see if we can swallow whatever we can.
+      WHILE: while (fr < fl) {
+        var swallowee = file[fr]
+
+        this.debug('\nglobstar while',
+                    file, fr, pattern, pr, swallowee)
+
+        // XXX remove this slice.  Just pass the start index.
+        if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
+          this.debug('globstar found match!', fr, fl, swallowee)
+          // found a match.
+          return true
+        } else {
+          // can't swallow "." or ".." ever.
+          // can only swallow ".foo" when explicitly asked.
+          if (swallowee === "." || swallowee === ".." ||
+              (!options.dot && swallowee.charAt(0) === ".")) {
+            this.debug("dot detected!", file, fr, pattern, pr)
+            break WHILE
+          }
+
+          // ** swallows a segment, and continue.
+          this.debug('globstar swallow a segment, and continue')
+          fr ++
+        }
+      }
+      // no match was found.
+      // However, in partial mode, we can't say this is necessarily over.
+      // If there's more *pattern* left, then 
+      if (partial) {
+        // ran out of file
+        this.debug("\n>>> no match, partial?", file, fr, pattern, pr)
+        if (fr === fl) return true
+      }
+      return false
+    }
+
+    // something other than **
+    // non-magic patterns just have to match exactly
+    // patterns with magic have been turned into regexps.
+    var hit
+    if (typeof p === "string") {
+      if (options.nocase) {
+        hit = f.toLowerCase() === p.toLowerCase()
+      } else {
+        hit = f === p
+      }
+      this.debug("string match", p, f, hit)
+    } else {
+      hit = f.match(p)
+      this.debug("pattern match", p, f, hit)
+    }
+
+    if (!hit) return false
+  }
+
+  // Note: ending in / means that we'll get a final ""
+  // at the end of the pattern.  This can only match a
+  // corresponding "" at the end of the file.
+  // If the file ends in /, then it can only match a
+  // a pattern that ends in /, unless the pattern just
+  // doesn't have any more for it. But, a/b/ should *not*
+  // match "a/b/*", even though "" matches against the
+  // [^/]*? pattern, except in partial mode, where it might
+  // simply not be reached yet.
+  // However, a/b/ should still satisfy a/*
+
+  // now either we fell off the end of the pattern, or we're done.
+  if (fi === fl && pi === pl) {
+    // ran out of pattern and filename at the same time.
+    // an exact hit!
+    return true
+  } else if (fi === fl) {
+    // ran out of file, but still had pattern left.
+    // this is ok if we're doing the match as part of
+    // a glob fs traversal.
+    return partial
+  } else if (pi === pl) {
+    // ran out of pattern, still have file left.
+    // this is only acceptable if we're on the very last
+    // empty segment of a file with a trailing slash.
+    // a/* should match a/b/
+    var emptyFileEnd = (fi === fl - 1) && (file[fi] === "")
+    return emptyFileEnd
+  }
+
+  // should be unreachable.
+  throw new Error("wtf?")
+}
+
+
+// replace stuff like \* with *
+function globUnescape (s) {
+  return s.replace(/\\(.)/g, "$1")
+}
+
+
+function regExpEscape (s) {
+  return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
+}
+
+})( typeof require === "function" ? require : null,
+    this,
+    typeof module === "object" ? module : null,
+    typeof process === "object" ? process.platform : "win32"
+  )
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+/node_modules
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS	(revision 533)
@@ -0,0 +1,14 @@
+# Authors, sorted by whether or not they are me
+Isaac Z. Schlueter <i@izs.me>
+Brian Cottingham <spiffytech@gmail.com>
+Carlos Brito Lage <carlos@carloslage.net>
+Jesse Dailey <jesse.dailey@gmail.com>
+Kevin O'Hara <kevinohara80@gmail.com>
+Marco Rogers <marco.rogers@gmail.com>
+Mark Cavage <mcavage@gmail.com>
+Marko Mikulicic <marko.mikulicic@isti.cnr.it>
+Nathan Rajlich <nathan@tootallnate.net>
+Satheesh Natesan <snateshan@myspace-inc.com>
+Trent Mick <trentm@gmail.com>
+ashleybrener <ashley@starlogik.com>
+n4kz <n4kz@n4kz.com>
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE	(revision 533)
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+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 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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md	(revision 533)
@@ -0,0 +1,97 @@
+# lru cache
+
+A cache object that deletes the least-recently-used items.
+
+## Usage:
+
+```javascript
+var LRU = require("lru-cache")
+  , options = { max: 500
+              , length: function (n) { return n * 2 }
+              , dispose: function (key, n) { n.close() }
+              , maxAge: 1000 * 60 * 60 }
+  , cache = LRU(options)
+  , otherCache = LRU(50) // sets just the max size
+
+cache.set("key", "value")
+cache.get("key") // "value"
+
+cache.reset()    // empty the cache
+```
+
+If you put more stuff in it, then items will fall out.
+
+If you try to put an oversized thing in it, then it'll fall out right
+away.
+
+## Options
+
+* `max` The maximum size of the cache, checked by applying the length
+  function to all values in the cache.  Not setting this is kind of
+  silly, since that's the whole purpose of this lib, but it defaults
+  to `Infinity`.
+* `maxAge` Maximum age in ms.  Items are not pro-actively pruned out
+  as they age, but if you try to get an item that is too old, it'll
+  drop it and return undefined instead of giving it to you.
+* `length` Function that is used to calculate the length of stored
+  items.  If you're storing strings or buffers, then you probably want
+  to do something like `function(n){return n.length}`.  The default is
+  `function(n){return 1}`, which is fine if you want to store `n`
+  like-sized things.
+* `dispose` Function that is called on items when they are dropped
+  from the cache.  This can be handy if you want to close file
+  descriptors or do other cleanup tasks when items are no longer
+  accessible.  Called with `key, value`.  It's called *before*
+  actually removing the item from the internal cache, so if you want
+  to immediately put it back in, you'll have to do that in a
+  `nextTick` or `setTimeout` callback or it won't do anything.
+* `stale` By default, if you set a `maxAge`, it'll only actually pull
+  stale items out of the cache when you `get(key)`.  (That is, it's
+  not pre-emptively doing a `setTimeout` or anything.)  If you set
+  `stale:true`, it'll return the stale value before deleting it.  If
+  you don't set this, then it'll return `undefined` when you try to
+  get a stale entry, as if it had already been deleted.
+
+## API
+
+* `set(key, value)`
+* `get(key) => value`
+
+    Both of these will update the "recently used"-ness of the key.
+    They do what you think.
+
+* `peek(key)`
+
+    Returns the key value (or `undefined` if not found) without
+    updating the "recently used"-ness of the key.
+
+    (If you find yourself using this a lot, you *might* be using the
+    wrong sort of data structure, but there are some use cases where
+    it's handy.)
+
+* `del(key)`
+
+    Deletes a key out of the cache.
+
+* `reset()`
+
+    Clear the cache entirely, throwing away all values.
+
+* `has(key)`
+
+    Check if a key is in the cache, without updating the recent-ness
+    or deleting it for being stale.
+
+* `forEach(function(value,key,cache), [thisp])`
+
+    Just like `Array.prototype.forEach`.  Iterates over all the keys
+    in the cache, in order of recent-ness.  (Ie, more recently used
+    items are iterated over first.)
+
+* `keys()`
+
+    Return an array of the keys in the cache.
+
+* `values()`
+
+    Return an array of the values in the cache.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js	(revision 533)
@@ -0,0 +1,252 @@
+;(function () { // closure for web browsers
+
+if (typeof module === 'object' && module.exports) {
+  module.exports = LRUCache
+} else {
+  // just set the global for non-node platforms.
+  this.LRUCache = LRUCache
+}
+
+function hOP (obj, key) {
+  return Object.prototype.hasOwnProperty.call(obj, key)
+}
+
+function naiveLength () { return 1 }
+
+function LRUCache (options) {
+  if (!(this instanceof LRUCache))
+    return new LRUCache(options)
+
+  if (typeof options === 'number')
+    options = { max: options }
+
+  if (!options)
+    options = {}
+
+  this._max = options.max
+  // Kind of weird to have a default max of Infinity, but oh well.
+  if (!this._max || !(typeof this._max === "number") || this._max <= 0 )
+    this._max = Infinity
+
+  this._lengthCalculator = options.length || naiveLength
+  if (typeof this._lengthCalculator !== "function")
+    this._lengthCalculator = naiveLength
+
+  this._allowStale = options.stale || false
+  this._maxAge = options.maxAge || null
+  this._dispose = options.dispose
+  this.reset()
+}
+
+// resize the cache when the max changes.
+Object.defineProperty(LRUCache.prototype, "max",
+  { set : function (mL) {
+      if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity
+      this._max = mL
+      if (this._length > this._max) trim(this)
+    }
+  , get : function () { return this._max }
+  , enumerable : true
+  })
+
+// resize the cache when the lengthCalculator changes.
+Object.defineProperty(LRUCache.prototype, "lengthCalculator",
+  { set : function (lC) {
+      if (typeof lC !== "function") {
+        this._lengthCalculator = naiveLength
+        this._length = this._itemCount
+        for (var key in this._cache) {
+          this._cache[key].length = 1
+        }
+      } else {
+        this._lengthCalculator = lC
+        this._length = 0
+        for (var key in this._cache) {
+          this._cache[key].length = this._lengthCalculator(this._cache[key].value)
+          this._length += this._cache[key].length
+        }
+      }
+
+      if (this._length > this._max) trim(this)
+    }
+  , get : function () { return this._lengthCalculator }
+  , enumerable : true
+  })
+
+Object.defineProperty(LRUCache.prototype, "length",
+  { get : function () { return this._length }
+  , enumerable : true
+  })
+
+
+Object.defineProperty(LRUCache.prototype, "itemCount",
+  { get : function () { return this._itemCount }
+  , enumerable : true
+  })
+
+LRUCache.prototype.forEach = function (fn, thisp) {
+  thisp = thisp || this
+  var i = 0;
+  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
+    i++
+    var hit = this._lruList[k]
+    if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
+      del(this, hit)
+      if (!this._allowStale) hit = undefined
+    }
+    if (hit) {
+      fn.call(thisp, hit.value, hit.key, this)
+    }
+  }
+}
+
+LRUCache.prototype.keys = function () {
+  var keys = new Array(this._itemCount)
+  var i = 0
+  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
+    var hit = this._lruList[k]
+    keys[i++] = hit.key
+  }
+  return keys
+}
+
+LRUCache.prototype.values = function () {
+  var values = new Array(this._itemCount)
+  var i = 0
+  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
+    var hit = this._lruList[k]
+    values[i++] = hit.value
+  }
+  return values
+}
+
+LRUCache.prototype.reset = function () {
+  if (this._dispose && this._cache) {
+    for (var k in this._cache) {
+      this._dispose(k, this._cache[k].value)
+    }
+  }
+
+  this._cache = Object.create(null) // hash of items by key
+  this._lruList = Object.create(null) // list of items in order of use recency
+  this._mru = 0 // most recently used
+  this._lru = 0 // least recently used
+  this._length = 0 // number of items in the list
+  this._itemCount = 0
+}
+
+// Provided for debugging/dev purposes only. No promises whatsoever that
+// this API stays stable.
+LRUCache.prototype.dump = function () {
+  return this._cache
+}
+
+LRUCache.prototype.dumpLru = function () {
+  return this._lruList
+}
+
+LRUCache.prototype.set = function (key, value) {
+  if (hOP(this._cache, key)) {
+    // dispose of the old one before overwriting
+    if (this._dispose) this._dispose(key, this._cache[key].value)
+    if (this._maxAge) this._cache[key].now = Date.now()
+    this._cache[key].value = value
+    this.get(key)
+    return true
+  }
+
+  var len = this._lengthCalculator(value)
+  var age = this._maxAge ? Date.now() : 0
+  var hit = new Entry(key, value, this._mru++, len, age)
+
+  // oversized objects fall out of cache automatically.
+  if (hit.length > this._max) {
+    if (this._dispose) this._dispose(key, value)
+    return false
+  }
+
+  this._length += hit.length
+  this._lruList[hit.lu] = this._cache[key] = hit
+  this._itemCount ++
+
+  if (this._length > this._max) trim(this)
+  return true
+}
+
+LRUCache.prototype.has = function (key) {
+  if (!hOP(this._cache, key)) return false
+  var hit = this._cache[key]
+  if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
+    return false
+  }
+  return true
+}
+
+LRUCache.prototype.get = function (key) {
+  return get(this, key, true)
+}
+
+LRUCache.prototype.peek = function (key) {
+  return get(this, key, false)
+}
+
+LRUCache.prototype.pop = function () {
+  var hit = this._lruList[this._lru]
+  del(this, hit)
+  return hit || null
+}
+
+LRUCache.prototype.del = function (key) {
+  del(this, this._cache[key])
+}
+
+function get (self, key, doUse) {
+  var hit = self._cache[key]
+  if (hit) {
+    if (self._maxAge && (Date.now() - hit.now > self._maxAge)) {
+      del(self, hit)
+      if (!self._allowStale) hit = undefined
+    } else {
+      if (doUse) use(self, hit)
+    }
+    if (hit) hit = hit.value
+  }
+  return hit
+}
+
+function use (self, hit) {
+  shiftLU(self, hit)
+  hit.lu = self._mru ++
+  self._lruList[hit.lu] = hit
+}
+
+function trim (self) {
+  while (self._lru < self._mru && self._length > self._max)
+    del(self, self._lruList[self._lru])
+}
+
+function shiftLU (self, hit) {
+  delete self._lruList[ hit.lu ]
+  while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++
+}
+
+function del (self, hit) {
+  if (hit) {
+    if (self._dispose) self._dispose(hit.key, hit.value)
+    self._length -= hit.length
+    self._itemCount --
+    delete self._cache[ hit.key ]
+    shiftLU(self, hit)
+  }
+}
+
+// classy, since V8 prefers predictable objects.
+function Entry (key, value, lu, length, now) {
+  this.key = key
+  this.value = value
+  this.lu = lu
+  this.length = length
+  this.now = now
+}
+
+})()
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json	(revision 533)
@@ -0,0 +1,33 @@
+{
+  "name": "lru-cache",
+  "description": "A cache object that deletes the least-recently-used items.",
+  "version": "2.5.0",
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me"
+  },
+  "scripts": {
+    "test": "tap test --gc"
+  },
+  "main": "lib/lru-cache.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/node-lru-cache.git"
+  },
+  "devDependencies": {
+    "tap": "",
+    "weak": ""
+  },
+  "license": {
+    "type": "MIT",
+    "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE"
+  },
+  "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n  , options = { max: 500\n              , length: function (n) { return n * 2 }\n              , dispose: function (key, n) { n.close() }\n              , maxAge: 1000 * 60 * 60 }\n  , cache = LRU(options)\n  , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset()    // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n  function to all values in the cache.  Not setting this is kind of\n  silly, since that's the whole purpose of this lib, but it defaults\n  to `Infinity`.\n* `maxAge` Maximum age in ms.  Items are not pro-actively pruned out\n  as they age, but if you try to get an item that is too old, it'll\n  drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n  items.  If you're storing strings or buffers, then you probably want\n  to do something like `function(n){return n.length}`.  The default is\n  `function(n){return 1}`, which is fine if you want to store `n`\n  like-sized things.\n* `dispose` Function that is called on items when they are dropped\n  from the cache.  This can be handy if you want to close file\n  descriptors or do other cleanup tasks when items are no longer\n  accessible.  Called with `key, value`.  It's called *before*\n  actually removing the item from the internal cache, so if you want\n  to immediately put it back in, you'll have to do that in a\n  `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n  stale items out of the cache when you `get(key)`.  (That is, it's\n  not pre-emptively doing a `setTimeout` or anything.)  If you set\n  `stale:true`, it'll return the stale value before deleting it.  If\n  you don't set this, then it'll return `undefined` when you try to\n  get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n    Both of these will update the \"recently used\"-ness of the key.\n    They do what you think.\n\n* `peek(key)`\n\n    Returns the key value (or `undefined` if not found) without\n    updating the \"recently used\"-ness of the key.\n\n    (If you find yourself using this a lot, you *might* be using the\n    wrong sort of data structure, but there are some use cases where\n    it's handy.)\n\n* `del(key)`\n\n    Deletes a key out of the cache.\n\n* `reset()`\n\n    Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n    Check if a key is in the cache, without updating the recent-ness\n    or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n    Just like `Array.prototype.forEach`.  Iterates over all the keys\n    in the cache, in order of recent-ness.  (Ie, more recently used\n    items are iterated over first.)\n\n* `keys()`\n\n    Return an array of the keys in the cache.\n\n* `values()`\n\n    Return an array of the values in the cache.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/node-lru-cache/issues"
+  },
+  "homepage": "https://github.com/isaacs/node-lru-cache",
+  "_id": "lru-cache@2.5.0",
+  "_from": "lru-cache@2"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js	(revision 533)
@@ -0,0 +1,369 @@
+var test = require("tap").test
+  , LRU = require("../")
+
+test("basic", function (t) {
+  var cache = new LRU({max: 10})
+  cache.set("key", "value")
+  t.equal(cache.get("key"), "value")
+  t.equal(cache.get("nada"), undefined)
+  t.equal(cache.length, 1)
+  t.equal(cache.max, 10)
+  t.end()
+})
+
+test("least recently set", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.set("c", "C")
+  t.equal(cache.get("c"), "C")
+  t.equal(cache.get("b"), "B")
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("lru recently gotten", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.get("a")
+  cache.set("c", "C")
+  t.equal(cache.get("c"), "C")
+  t.equal(cache.get("b"), undefined)
+  t.equal(cache.get("a"), "A")
+  t.end()
+})
+
+test("del", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.del("a")
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("max", function (t) {
+  var cache = new LRU(3)
+
+  // test changing the max, verify that the LRU items get dropped.
+  cache.max = 100
+  for (var i = 0; i < 100; i ++) cache.set(i, i)
+  t.equal(cache.length, 100)
+  for (var i = 0; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+  cache.max = 3
+  t.equal(cache.length, 3)
+  for (var i = 0; i < 97; i ++) {
+    t.equal(cache.get(i), undefined)
+  }
+  for (var i = 98; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+
+  // now remove the max restriction, and try again.
+  cache.max = "hello"
+  for (var i = 0; i < 100; i ++) cache.set(i, i)
+  t.equal(cache.length, 100)
+  for (var i = 0; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+  // should trigger an immediate resize
+  cache.max = 3
+  t.equal(cache.length, 3)
+  for (var i = 0; i < 97; i ++) {
+    t.equal(cache.get(i), undefined)
+  }
+  for (var i = 98; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+  t.end()
+})
+
+test("reset", function (t) {
+  var cache = new LRU(10)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.reset()
+  t.equal(cache.length, 0)
+  t.equal(cache.max, 10)
+  t.equal(cache.get("a"), undefined)
+  t.equal(cache.get("b"), undefined)
+  t.end()
+})
+
+
+// Note: `<cache>.dump()` is a debugging tool only. No guarantees are made
+// about the format/layout of the response.
+test("dump", function (t) {
+  var cache = new LRU(10)
+  var d = cache.dump();
+  t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache")
+  cache.set("a", "A")
+  var d = cache.dump()  // { a: { key: "a", value: "A", lu: 0 } }
+  t.ok(d.a)
+  t.equal(d.a.key, "a")
+  t.equal(d.a.value, "A")
+  t.equal(d.a.lu, 0)
+
+  cache.set("b", "B")
+  cache.get("b")
+  d = cache.dump()
+  t.ok(d.b)
+  t.equal(d.b.key, "b")
+  t.equal(d.b.value, "B")
+  t.equal(d.b.lu, 2)
+
+  t.end()
+})
+
+
+test("basic with weighed length", function (t) {
+  var cache = new LRU({
+    max: 100,
+    length: function (item) { return item.size }
+  })
+  cache.set("key", {val: "value", size: 50})
+  t.equal(cache.get("key").val, "value")
+  t.equal(cache.get("nada"), undefined)
+  t.equal(cache.lengthCalculator(cache.get("key")), 50)
+  t.equal(cache.length, 50)
+  t.equal(cache.max, 100)
+  t.end()
+})
+
+
+test("weighed length item too large", function (t) {
+  var cache = new LRU({
+    max: 10,
+    length: function (item) { return item.size }
+  })
+  t.equal(cache.max, 10)
+
+  // should fall out immediately
+  cache.set("key", {val: "value", size: 50})
+
+  t.equal(cache.length, 0)
+  t.equal(cache.get("key"), undefined)
+  t.end()
+})
+
+test("least recently set with weighed length", function (t) {
+  var cache = new LRU({
+    max:8,
+    length: function (item) { return item.length }
+  })
+  cache.set("a", "A")
+  cache.set("b", "BB")
+  cache.set("c", "CCC")
+  cache.set("d", "DDDD")
+  t.equal(cache.get("d"), "DDDD")
+  t.equal(cache.get("c"), "CCC")
+  t.equal(cache.get("b"), undefined)
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("lru recently gotten with weighed length", function (t) {
+  var cache = new LRU({
+    max: 8,
+    length: function (item) { return item.length }
+  })
+  cache.set("a", "A")
+  cache.set("b", "BB")
+  cache.set("c", "CCC")
+  cache.get("a")
+  cache.get("b")
+  cache.set("d", "DDDD")
+  t.equal(cache.get("c"), undefined)
+  t.equal(cache.get("d"), "DDDD")
+  t.equal(cache.get("b"), "BB")
+  t.equal(cache.get("a"), "A")
+  t.end()
+})
+
+test("set returns proper booleans", function(t) {
+  var cache = new LRU({
+    max: 5,
+    length: function (item) { return item.length }
+  })
+
+  t.equal(cache.set("a", "A"), true)
+
+  // should return false for max exceeded
+  t.equal(cache.set("b", "donuts"), false)
+
+  t.equal(cache.set("b", "B"), true)
+  t.equal(cache.set("c", "CCCC"), true)
+  t.end()
+})
+
+test("drop the old items", function(t) {
+  var cache = new LRU({
+    max: 5,
+    maxAge: 50
+  })
+
+  cache.set("a", "A")
+
+  setTimeout(function () {
+    cache.set("b", "b")
+    t.equal(cache.get("a"), "A")
+  }, 25)
+
+  setTimeout(function () {
+    cache.set("c", "C")
+    // timed out
+    t.notOk(cache.get("a"))
+  }, 60)
+
+  setTimeout(function () {
+    t.notOk(cache.get("b"))
+    t.equal(cache.get("c"), "C")
+  }, 90)
+
+  setTimeout(function () {
+    t.notOk(cache.get("c"))
+    t.end()
+  }, 155)
+})
+
+test("disposal function", function(t) {
+  var disposed = false
+  var cache = new LRU({
+    max: 1,
+    dispose: function (k, n) {
+      disposed = n
+    }
+  })
+
+  cache.set(1, 1)
+  cache.set(2, 2)
+  t.equal(disposed, 1)
+  cache.set(3, 3)
+  t.equal(disposed, 2)
+  cache.reset()
+  t.equal(disposed, 3)
+  t.end()
+})
+
+test("disposal function on too big of item", function(t) {
+  var disposed = false
+  var cache = new LRU({
+    max: 1,
+    length: function (k) {
+      return k.length
+    },
+    dispose: function (k, n) {
+      disposed = n
+    }
+  })
+  var obj = [ 1, 2 ]
+
+  t.equal(disposed, false)
+  cache.set("obj", obj)
+  t.equal(disposed, obj)
+  t.end()
+})
+
+test("has()", function(t) {
+  var cache = new LRU({
+    max: 1,
+    maxAge: 10
+  })
+
+  cache.set('foo', 'bar')
+  t.equal(cache.has('foo'), true)
+  cache.set('blu', 'baz')
+  t.equal(cache.has('foo'), false)
+  t.equal(cache.has('blu'), true)
+  setTimeout(function() {
+    t.equal(cache.has('blu'), false)
+    t.end()
+  }, 15)
+})
+
+test("stale", function(t) {
+  var cache = new LRU({
+    maxAge: 10,
+    stale: true
+  })
+
+  cache.set('foo', 'bar')
+  t.equal(cache.get('foo'), 'bar')
+  t.equal(cache.has('foo'), true)
+  setTimeout(function() {
+    t.equal(cache.has('foo'), false)
+    t.equal(cache.get('foo'), 'bar')
+    t.equal(cache.get('foo'), undefined)
+    t.end()
+  }, 15)
+})
+
+test("lru update via set", function(t) {
+  var cache = LRU({ max: 2 });
+
+  cache.set('foo', 1);
+  cache.set('bar', 2);
+  cache.del('bar');
+  cache.set('baz', 3);
+  cache.set('qux', 4);
+
+  t.equal(cache.get('foo'), undefined)
+  t.equal(cache.get('bar'), undefined)
+  t.equal(cache.get('baz'), 3)
+  t.equal(cache.get('qux'), 4)
+  t.end()
+})
+
+test("least recently set w/ peek", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  t.equal(cache.peek("a"), "A")
+  cache.set("c", "C")
+  t.equal(cache.get("c"), "C")
+  t.equal(cache.get("b"), "B")
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("pop the least used item", function (t) {
+  var cache = new LRU(3)
+  , last
+
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.set("c", "C")
+
+  t.equal(cache.length, 3)
+  t.equal(cache.max, 3)
+
+  // Ensure we pop a, c, b
+  cache.get("b", "B")
+
+  last = cache.pop()
+  t.equal(last.key, "a")
+  t.equal(last.value, "A")
+  t.equal(cache.length, 2)
+  t.equal(cache.max, 3)
+
+  last = cache.pop()
+  t.equal(last.key, "c")
+  t.equal(last.value, "C")
+  t.equal(cache.length, 1)
+  t.equal(cache.max, 3)
+
+  last = cache.pop()
+  t.equal(last.key, "b")
+  t.equal(last.value, "B")
+  t.equal(cache.length, 0)
+  t.equal(cache.max, 3)
+
+  last = cache.pop()
+  t.equal(last, null)
+  t.equal(cache.length, 0)
+  t.equal(cache.max, 3)
+
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js	(revision 533)
@@ -0,0 +1,52 @@
+var test = require('tap').test
+var LRU = require('../')
+
+test('forEach', function (t) {
+  var l = new LRU(5)
+  for (var i = 0; i < 10; i ++) {
+    l.set(i.toString(), i.toString(2))
+  }
+
+  var i = 9
+  l.forEach(function (val, key, cache) {
+    t.equal(cache, l)
+    t.equal(key, i.toString())
+    t.equal(val, i.toString(2))
+    i -= 1
+  })
+
+  // get in order of most recently used
+  l.get(6)
+  l.get(8)
+
+  var order = [ 8, 6, 9, 7, 5 ]
+  var i = 0
+
+  l.forEach(function (val, key, cache) {
+    var j = order[i ++]
+    t.equal(cache, l)
+    t.equal(key, j.toString())
+    t.equal(val, j.toString(2))
+  })
+
+  t.end()
+})
+
+test('keys() and values()', function (t) {
+  var l = new LRU(5)
+  for (var i = 0; i < 10; i ++) {
+    l.set(i.toString(), i.toString(2))
+  }
+
+  t.similar(l.keys(), ['9', '8', '7', '6', '5'])
+  t.similar(l.values(), ['1001', '1000', '111', '110', '101'])
+
+  // get in order of most recently used
+  l.get(6)
+  l.get(8)
+
+  t.similar(l.keys(), ['8', '6', '9', '7', '5'])
+  t.similar(l.values(), ['1000', '110', '1001', '111', '101'])
+
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js	(revision 533)
@@ -0,0 +1,50 @@
+#!/usr/bin/env node --expose_gc
+
+var weak = require('weak');
+var test = require('tap').test
+var LRU = require('../')
+var l = new LRU({ max: 10 })
+var refs = 0
+function X() {
+  refs ++
+  weak(this, deref)
+}
+
+function deref() {
+  refs --
+}
+
+test('no leaks', function (t) {
+  // fill up the cache
+  for (var i = 0; i < 100; i++) {
+    l.set(i, new X);
+    // throw some gets in there, too.
+    if (i % 2 === 0)
+      l.get(i / 2)
+  }
+
+  gc()
+
+  var start = process.memoryUsage()
+
+  // capture the memory
+  var startRefs = refs
+
+  // do it again, but more
+  for (var i = 0; i < 10000; i++) {
+    l.set(i, new X);
+    // throw some gets in there, too.
+    if (i % 2 === 0)
+      l.get(i / 2)
+  }
+
+  gc()
+
+  var end = process.memoryUsage()
+  t.equal(refs, startRefs, 'no leaky refs')
+
+  console.error('start: %j\n' +
+                'end:   %j', start, end);
+  t.pass();
+  t.end();
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE	(revision 533)
@@ -0,0 +1,27 @@
+Copyright (c) Isaac Z. Schlueter ("Author")
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md	(revision 533)
@@ -0,0 +1,53 @@
+# sigmund
+
+Quick and dirty signatures for Objects.
+
+This is like a much faster `deepEquals` comparison, which returns a
+string key suitable for caches and the like.
+
+## Usage
+
+```javascript
+function doSomething (someObj) {
+  var key = sigmund(someObj, maxDepth) // max depth defaults to 10
+  var cached = cache.get(key)
+  if (cached) return cached)
+
+  var result = expensiveCalculation(someObj)
+  cache.set(key, result)
+  return result
+}
+```
+
+The resulting key will be as unique and reproducible as calling
+`JSON.stringify` or `util.inspect` on the object, but is much faster.
+In order to achieve this speed, some differences are glossed over.
+For example, the object `{0:'foo'}` will be treated identically to the
+array `['foo']`.
+
+Also, just as there is no way to summon the soul from the scribblings
+of a cocain-addled psychoanalyst, there is no way to revive the object
+from the signature string that sigmund gives you.  In fact, it's
+barely even readable.
+
+As with `sys.inspect` and `JSON.stringify`, larger objects will
+produce larger signature strings.
+
+Because sigmund is a bit less strict than the more thorough
+alternatives, the strings will be shorter, and also there is a
+slightly higher chance for collisions.  For example, these objects
+have the same signature:
+
+    var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}
+    var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}
+
+Like a good Freudian, sigmund is most effective when you already have
+some understanding of what you're looking for.  It can help you help
+yourself, but you must be willing to do some work as well.
+
+Cycles are handled, and cyclical objects are silently omitted (though
+the key is included in the signature output.)
+
+The second argument is the maximum depth, which defaults to 10,
+because that is the maximum object traversal depth covered by most
+insurance carriers.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js	(revision 533)
@@ -0,0 +1,283 @@
+// different ways to id objects
+// use a req/res pair, since it's crazy deep and cyclical
+
+// sparseFE10 and sigmund are usually pretty close, which is to be expected,
+// since they are essentially the same algorithm, except that sigmund handles
+// regular expression objects properly.
+
+
+var http = require('http')
+var util = require('util')
+var sigmund = require('./sigmund.js')
+var sreq, sres, creq, cres, test
+
+http.createServer(function (q, s) {
+  sreq = q
+  sres = s
+  sres.end('ok')
+  this.close(function () { setTimeout(function () {
+    start()
+  }, 200) })
+}).listen(1337, function () {
+  creq = http.get({ port: 1337 })
+  creq.on('response', function (s) { cres = s })
+})
+
+function start () {
+  test = [sreq, sres, creq, cres]
+  // test = sreq
+  // sreq.sres = sres
+  // sreq.creq = creq
+  // sreq.cres = cres
+
+  for (var i in exports.compare) {
+    console.log(i)
+    var hash = exports.compare[i]()
+    console.log(hash)
+    console.log(hash.length)
+    console.log('')
+  }
+
+  require('bench').runMain()
+}
+
+function customWs (obj, md, d) {
+  d = d || 0
+  var to = typeof obj
+  if (to === 'undefined' || to === 'function' || to === null) return ''
+  if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '')
+
+  if (Array.isArray(obj)) {
+    return obj.map(function (i, _, __) {
+      return customWs(i, md, d + 1)
+    }).reduce(function (a, b) { return a + b }, '')
+  }
+
+  var keys = Object.keys(obj)
+  return keys.map(function (k, _, __) {
+    return k + ':' + customWs(obj[k], md, d + 1)
+  }).reduce(function (a, b) { return a + b }, '')
+}
+
+function custom (obj, md, d) {
+  d = d || 0
+  var to = typeof obj
+  if (to === 'undefined' || to === 'function' || to === null) return ''
+  if (d > md || !obj || to !== 'object') return '' + obj
+
+  if (Array.isArray(obj)) {
+    return obj.map(function (i, _, __) {
+      return custom(i, md, d + 1)
+    }).reduce(function (a, b) { return a + b }, '')
+  }
+
+  var keys = Object.keys(obj)
+  return keys.map(function (k, _, __) {
+    return k + ':' + custom(obj[k], md, d + 1)
+  }).reduce(function (a, b) { return a + b }, '')
+}
+
+function sparseFE2 (obj, maxDepth) {
+  var seen = []
+  var soFar = ''
+  function ch (v, depth) {
+    if (depth > maxDepth) return
+    if (typeof v === 'function' || typeof v === 'undefined') return
+    if (typeof v !== 'object' || !v) {
+      soFar += v
+      return
+    }
+    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
+    seen.push(v)
+    soFar += '{'
+    Object.keys(v).forEach(function (k, _, __) {
+      // pseudo-private values.  skip those.
+      if (k.charAt(0) === '_') return
+      var to = typeof v[k]
+      if (to === 'function' || to === 'undefined') return
+      soFar += k + ':'
+      ch(v[k], depth + 1)
+    })
+    soFar += '}'
+  }
+  ch(obj, 0)
+  return soFar
+}
+
+function sparseFE (obj, maxDepth) {
+  var seen = []
+  var soFar = ''
+  function ch (v, depth) {
+    if (depth > maxDepth) return
+    if (typeof v === 'function' || typeof v === 'undefined') return
+    if (typeof v !== 'object' || !v) {
+      soFar += v
+      return
+    }
+    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
+    seen.push(v)
+    soFar += '{'
+    Object.keys(v).forEach(function (k, _, __) {
+      // pseudo-private values.  skip those.
+      if (k.charAt(0) === '_') return
+      var to = typeof v[k]
+      if (to === 'function' || to === 'undefined') return
+      soFar += k
+      ch(v[k], depth + 1)
+    })
+  }
+  ch(obj, 0)
+  return soFar
+}
+
+function sparse (obj, maxDepth) {
+  var seen = []
+  var soFar = ''
+  function ch (v, depth) {
+    if (depth > maxDepth) return
+    if (typeof v === 'function' || typeof v === 'undefined') return
+    if (typeof v !== 'object' || !v) {
+      soFar += v
+      return
+    }
+    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
+    seen.push(v)
+    soFar += '{'
+    for (var k in v) {
+      // pseudo-private values.  skip those.
+      if (k.charAt(0) === '_') continue
+      var to = typeof v[k]
+      if (to === 'function' || to === 'undefined') continue
+      soFar += k
+      ch(v[k], depth + 1)
+    }
+  }
+  ch(obj, 0)
+  return soFar
+}
+
+function noCommas (obj, maxDepth) {
+  var seen = []
+  var soFar = ''
+  function ch (v, depth) {
+    if (depth > maxDepth) return
+    if (typeof v === 'function' || typeof v === 'undefined') return
+    if (typeof v !== 'object' || !v) {
+      soFar += v
+      return
+    }
+    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
+    seen.push(v)
+    soFar += '{'
+    for (var k in v) {
+      // pseudo-private values.  skip those.
+      if (k.charAt(0) === '_') continue
+      var to = typeof v[k]
+      if (to === 'function' || to === 'undefined') continue
+      soFar += k + ':'
+      ch(v[k], depth + 1)
+    }
+    soFar += '}'
+  }
+  ch(obj, 0)
+  return soFar
+}
+
+
+function flatten (obj, maxDepth) {
+  var seen = []
+  var soFar = ''
+  function ch (v, depth) {
+    if (depth > maxDepth) return
+    if (typeof v === 'function' || typeof v === 'undefined') return
+    if (typeof v !== 'object' || !v) {
+      soFar += v
+      return
+    }
+    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
+    seen.push(v)
+    soFar += '{'
+    for (var k in v) {
+      // pseudo-private values.  skip those.
+      if (k.charAt(0) === '_') continue
+      var to = typeof v[k]
+      if (to === 'function' || to === 'undefined') continue
+      soFar += k + ':'
+      ch(v[k], depth + 1)
+      soFar += ','
+    }
+    soFar += '}'
+  }
+  ch(obj, 0)
+  return soFar
+}
+
+exports.compare =
+{
+  // 'custom 2': function () {
+  //   return custom(test, 2, 0)
+  // },
+  // 'customWs 2': function () {
+  //   return customWs(test, 2, 0)
+  // },
+  'JSON.stringify (guarded)': function () {
+    var seen = []
+    return JSON.stringify(test, function (k, v) {
+      if (typeof v !== 'object' || !v) return v
+      if (seen.indexOf(v) !== -1) return undefined
+      seen.push(v)
+      return v
+    })
+  },
+
+  'flatten 10': function () {
+    return flatten(test, 10)
+  },
+
+  // 'flattenFE 10': function () {
+  //   return flattenFE(test, 10)
+  // },
+
+  'noCommas 10': function () {
+    return noCommas(test, 10)
+  },
+
+  'sparse 10': function () {
+    return sparse(test, 10)
+  },
+
+  'sparseFE 10': function () {
+    return sparseFE(test, 10)
+  },
+
+  'sparseFE2 10': function () {
+    return sparseFE2(test, 10)
+  },
+
+  sigmund: function() {
+    return sigmund(test, 10)
+  },
+
+
+  // 'util.inspect 1': function () {
+  //   return util.inspect(test, false, 1, false)
+  // },
+  // 'util.inspect undefined': function () {
+  //   util.inspect(test)
+  // },
+  // 'util.inspect 2': function () {
+  //   util.inspect(test, false, 2, false)
+  // },
+  // 'util.inspect 3': function () {
+  //   util.inspect(test, false, 3, false)
+  // },
+  // 'util.inspect 4': function () {
+  //   util.inspect(test, false, 4, false)
+  // },
+  // 'util.inspect Infinity': function () {
+  //   util.inspect(test, false, Infinity, false)
+  // }
+}
+
+/** results
+**/
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json	(revision 533)
@@ -0,0 +1,42 @@
+{
+  "name": "sigmund",
+  "version": "1.0.0",
+  "description": "Quick and dirty signatures for Objects.",
+  "main": "sigmund.js",
+  "directories": {
+    "test": "test"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "tap": "~0.3.0"
+  },
+  "scripts": {
+    "test": "tap test/*.js",
+    "bench": "node bench.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/sigmund"
+  },
+  "keywords": [
+    "object",
+    "signature",
+    "key",
+    "data",
+    "psychoanalysis"
+  ],
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me/"
+  },
+  "license": "BSD",
+  "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n  var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n  var cached = cache.get(key)\n  if (cached) return cached)\n\n  var result = expensiveCalculation(someObj)\n  cache.set(key, result)\n  return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you.  In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions.  For example, these objects\nhave the same signature:\n\n    var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n    var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for.  It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/sigmund/issues"
+  },
+  "homepage": "https://github.com/isaacs/sigmund",
+  "_id": "sigmund@1.0.0",
+  "_from": "sigmund@~1.0.0"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js	(revision 533)
@@ -0,0 +1,39 @@
+module.exports = sigmund
+function sigmund (subject, maxSessions) {
+    maxSessions = maxSessions || 10;
+    var notes = [];
+    var analysis = '';
+    var RE = RegExp;
+
+    function psychoAnalyze (subject, session) {
+        if (session > maxSessions) return;
+
+        if (typeof subject === 'function' ||
+            typeof subject === 'undefined') {
+            return;
+        }
+
+        if (typeof subject !== 'object' || !subject ||
+            (subject instanceof RE)) {
+            analysis += subject;
+            return;
+        }
+
+        if (notes.indexOf(subject) !== -1 || session === maxSessions) return;
+
+        notes.push(subject);
+        analysis += '{';
+        Object.keys(subject).forEach(function (issue, _, __) {
+            // pseudo-private values.  skip those.
+            if (issue.charAt(0) === '_') return;
+            var to = typeof subject[issue];
+            if (to === 'function' || to === 'undefined') return;
+            analysis += issue;
+            psychoAnalyze(subject[issue], session + 1);
+        });
+    }
+    psychoAnalyze(subject, 0);
+    return analysis;
+}
+
+// vim: set softtabstop=4 shiftwidth=4:
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js	(revision 533)
@@ -0,0 +1,24 @@
+var test = require('tap').test
+var sigmund = require('../sigmund.js')
+
+
+// occasionally there are duplicates
+// that's an acceptable edge-case.  JSON.stringify and util.inspect
+// have some collision potential as well, though less, and collision
+// detection is expensive.
+var hash = '{abc/def/g{0h1i2{jkl'
+var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}
+var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}
+
+var obj3 = JSON.parse(JSON.stringify(obj1))
+obj3.c = /def/
+obj3.g[2].cycle = obj3
+var cycleHash = '{abc/def/g{0h1i2{jklcycle'
+
+test('basic', function (t) {
+    t.equal(sigmund(obj1), hash)
+    t.equal(sigmund(obj2), hash)
+    t.equal(sigmund(obj3), cycleHash)
+    t.end()
+})
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json	(revision 533)
@@ -0,0 +1,40 @@
+{
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me"
+  },
+  "name": "minimatch",
+  "description": "a glob matcher in javascript",
+  "version": "0.2.14",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/minimatch.git"
+  },
+  "main": "minimatch.js",
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "engines": {
+    "node": "*"
+  },
+  "dependencies": {
+    "lru-cache": "2",
+    "sigmund": "~1.0.0"
+  },
+  "devDependencies": {
+    "tap": ""
+  },
+  "license": {
+    "type": "MIT",
+    "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE"
+  },
+  "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\nminimatch(\"bar.foo\", \"*.+(bar|foo)\", { debug: true }) // true, and noisy!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n  Each row in the\n  array corresponds to a brace-expanded pattern.  Each item in the row\n  corresponds to a single path-part.  For example, the pattern\n  `{a,b/c}/d` would expand to a set of patterns like:\n\n        [ [ a, d ]\n        , [ b, c, d ] ]\n\n    If a portion of the pattern doesn't have any \"magic\" in it\n    (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n    will be left as a string rather than converted to a regular\n    expression.\n\n* `regexp` Created by the `makeRe` method.  A single regular expression\n  expressing the entire pattern.  This is useful in cases where you wish\n  to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n  Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n  false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n  filename, and match it against a single row in the `regExpSet`.  This\n  method is mainly for internal use, but is exposed so that it can be\n  used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items.  So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export.  Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`.  Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob.  If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself.  When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes.  For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated.  Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally.  This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything.  Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set.  This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not.\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes.  For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`.  This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern.  Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity.  Since those two are valid, matching proceeds.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/minimatch/issues"
+  },
+  "homepage": "https://github.com/isaacs/minimatch",
+  "_id": "minimatch@0.2.14",
+  "_from": "minimatch@~0.2.11"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js	(revision 533)
@@ -0,0 +1,399 @@
+// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test
+//
+// TODO: Some of these tests do very bad things with backslashes, and will
+// most likely fail badly on windows.  They should probably be skipped.
+
+var tap = require("tap")
+  , globalBefore = Object.keys(global)
+  , mm = require("../")
+  , files = [ "a", "b", "c", "d", "abc"
+            , "abd", "abe", "bb", "bcd"
+            , "ca", "cb", "dd", "de"
+            , "bdir/", "bdir/cfile"]
+  , next = files.concat([ "a-b", "aXb"
+                        , ".x", ".y" ])
+
+
+var patterns =
+  [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test"
+  , ["a*", ["a", "abc", "abd", "abe"]]
+  , ["X*", ["X*"], {nonull: true}]
+
+  // allow null glob expansion
+  , ["X*", []]
+
+  // isaacs: Slightly different than bash/sh/ksh
+  // \\* is not un-escaped to literal "*" in a failed match,
+  // but it does make it get treated as a literal star
+  , ["\\*", ["\\*"], {nonull: true}]
+  , ["\\**", ["\\**"], {nonull: true}]
+  , ["\\*\\*", ["\\*\\*"], {nonull: true}]
+
+  , ["b*/", ["bdir/"]]
+  , ["c*", ["c", "ca", "cb"]]
+  , ["**", files]
+
+  , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}]
+  , ["s/\\..*//", ["s/\\..*//"], {nonull: true}]
+
+  , "legendary larry crashes bashes"
+  , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"
+    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}]
+  , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"
+    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}]
+
+  , "character classes"
+  , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]]
+  , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd",
+     "bdir/", "ca", "cb", "dd", "de"]]
+  , ["a*[^c]", ["abd", "abe"]]
+  , function () { files.push("a-b", "aXb") }
+  , ["a[X-]b", ["a-b", "aXb"]]
+  , function () { files.push(".x", ".y") }
+  , ["[^a-c]*", ["d", "dd", "de"]]
+  , function () { files.push("a*b/", "a*b/ooo") }
+  , ["a\\*b/*", ["a*b/ooo"]]
+  , ["a\\*?/*", ["a*b/ooo"]]
+  , ["*\\\\!*", [], {null: true}, ["echo !7"]]
+  , ["*\\!*", ["echo !7"], null, ["echo !7"]]
+  , ["*.\\*", ["r.*"], null, ["r.*"]]
+  , ["a[b]c", ["abc"]]
+  , ["a[\\b]c", ["abc"]]
+  , ["a?c", ["abc"]]
+  , ["a\\*c", [], {null: true}, ["abc"]]
+  , ["", [""], { null: true }, [""]]
+
+  , "http://www.opensource.apple.com/source/bash/bash-23/" +
+    "bash/tests/glob-test"
+  , function () { files.push("man/", "man/man1/", "man/man1/bash.1") }
+  , ["*/man*/bash.*", ["man/man1/bash.1"]]
+  , ["man/man1/bash.1", ["man/man1/bash.1"]]
+  , ["a***c", ["abc"], null, ["abc"]]
+  , ["a*****?c", ["abc"], null, ["abc"]]
+  , ["?*****??", ["abc"], null, ["abc"]]
+  , ["*****??", ["abc"], null, ["abc"]]
+  , ["?*****?c", ["abc"], null, ["abc"]]
+  , ["?***?****c", ["abc"], null, ["abc"]]
+  , ["?***?****?", ["abc"], null, ["abc"]]
+  , ["?***?****", ["abc"], null, ["abc"]]
+  , ["*******c", ["abc"], null, ["abc"]]
+  , ["*******?", ["abc"], null, ["abc"]]
+  , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+  , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+  , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+  , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+  , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+  , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+  , ["[-abc]", ["-"], null, ["-"]]
+  , ["[abc-]", ["-"], null, ["-"]]
+  , ["\\", ["\\"], null, ["\\"]]
+  , ["[\\\\]", ["\\"], null, ["\\"]]
+  , ["[[]", ["["], null, ["["]]
+  , ["[", ["["], null, ["["]]
+  , ["[*", ["[abc"], null, ["[abc"]]
+  , "a right bracket shall lose its special meaning and\n" +
+    "represent itself in a bracket expression if it occurs\n" +
+    "first in the list.  -- POSIX.2 2.8.3.2"
+  , ["[]]", ["]"], null, ["]"]]
+  , ["[]-]", ["]"], null, ["]"]]
+  , ["[a-\z]", ["p"], null, ["p"]]
+  , ["??**********?****?", [], { null: true }, ["abc"]]
+  , ["??**********?****c", [], { null: true }, ["abc"]]
+  , ["?************c****?****", [], { null: true }, ["abc"]]
+  , ["*c*?**", [], { null: true }, ["abc"]]
+  , ["a*****c*?**", [], { null: true }, ["abc"]]
+  , ["a********???*******", [], { null: true }, ["abc"]]
+  , ["[]", [], { null: true }, ["a"]]
+  , ["[abc", [], { null: true }, ["["]]
+
+  , "nocase tests"
+  , ["XYZ", ["xYz"], { nocase: true, null: true }
+    , ["xYz", "ABC", "IjK"]]
+  , ["ab*", ["ABC"], { nocase: true, null: true }
+    , ["xYz", "ABC", "IjK"]]
+  , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true }
+    , ["xYz", "ABC", "IjK"]]
+
+  // [ pattern, [matches], MM opts, files, TAP opts]
+  , "onestar/twostar"
+  , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]]
+  , ["{/?,*}", ["/a", "bb"], {null: true}
+    , ["/a", "/b/b", "/a/b/c", "bb"]]
+
+  , "dots should not match unless requested"
+  , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]]
+
+  // .. and . can only match patterns starting with .,
+  // even when options.dot is set.
+  , function () {
+      files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"]
+    }
+  , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}]
+  , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}]
+  , ["a/*/b", ["a/c/b"], {dot:false}]
+  , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}]
+
+
+  // this also tests that changing the options needs
+  // to change the cache key, even if the pattern is
+  // the same!
+  , ["**", ["a/b","a/.d",".a/.d"], { dot: true }
+    , [ ".a/.d", "a/.d", "a/b"]]
+
+  , "paren sets cannot contain slashes"
+  , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]]
+
+  // brace sets trump all else.
+  //
+  // invalid glob pattern.  fails on bash4 and bsdglob.
+  // however, in this implementation, it's easier just
+  // to do the intuitive thing, and let brace-expansion
+  // actually come before parsing any extglob patterns,
+  // like the documentation seems to say.
+  //
+  // XXX: if anyone complains about this, either fix it
+  // or tell them to grow up and stop complaining.
+  //
+  // bash/bsdglob says this:
+  // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]]
+  // but we do this instead:
+  , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]]
+
+  // test partial parsing in the presence of comment/negation chars
+  , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]]
+  , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]]
+
+  // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped.
+  , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g"
+    , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"]
+    , {}
+    , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]]
+
+
+  // crazy nested {,,} and *(||) tests.
+  , function () {
+      files = [ "a", "b", "c", "d"
+              , "ab", "ac", "ad"
+              , "bc", "cb"
+              , "bc,d", "c,db", "c,d"
+              , "d)", "(b|c", "*(b|c"
+              , "b|c", "b|cc", "cb|c"
+              , "x(a|b|c)", "x(a|c)"
+              , "(a|b|c)", "(a|c)"]
+    }
+  , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]]
+  , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]]
+  // a
+  // *(b|c)
+  // *(b|d)
+  , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]]
+  , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]]
+
+
+  // test various flag settings.
+  , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"]
+    , { noext: true } ]
+  , ["a?b", ["x/y/acb", "acb/"], {matchBase: true}
+    , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ]
+  , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]]
+
+
+  // begin channelling Boole and deMorgan...
+  , "negation tests"
+  , function () {
+      files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"]
+    }
+
+  // anything that is NOT a* matches.
+  , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]]
+
+  // anything that IS !a* matches.
+  , ["!a*", ["!ab", "!abc"], {nonegate: true}]
+
+  // anything that IS a* matches
+  , ["!!a*", ["a!b"]]
+
+  // anything that is NOT !a* matches
+  , ["!\\!a*", ["a!b", "d", "e", "\\!a"]]
+
+  // negation nestled within a pattern
+  , function () {
+      files = [ "foo.js"
+              , "foo.bar"
+              // can't match this one without negative lookbehind.
+              , "foo.js.js"
+              , "blar.js"
+              , "foo."
+              , "boo.js.boo" ]
+    }
+  , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
+
+  // https://github.com/isaacs/minimatch/issues/5
+  , function () {
+      files = [ 'a/b/.x/c'
+              , 'a/b/.x/c/d'
+              , 'a/b/.x/c/d/e'
+              , 'a/b/.x'
+              , 'a/b/.x/'
+              , 'a/.x/b'
+              , '.x'
+              , '.x/'
+              , '.x/a'
+              , '.x/a/b'
+              , 'a/.x/b/.x/c'
+              , '.x/.x' ]
+  }
+  , ["**/.x/**", [ '.x/'
+                 , '.x/a'
+                 , '.x/a/b'
+                 , 'a/.x/b'
+                 , 'a/b/.x/'
+                 , 'a/b/.x/c'
+                 , 'a/b/.x/c/d'
+                 , 'a/b/.x/c/d/e' ] ]
+
+  ]
+
+var regexps =
+  [ '/^(?:(?=.)a[^/]*?)$/',
+    '/^(?:(?=.)X[^/]*?)$/',
+    '/^(?:(?=.)X[^/]*?)$/',
+    '/^(?:\\*)$/',
+    '/^(?:(?=.)\\*[^/]*?)$/',
+    '/^(?:\\*\\*)$/',
+    '/^(?:(?=.)b[^/]*?\\/)$/',
+    '/^(?:(?=.)c[^/]*?)$/',
+    '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
+    '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/',
+    '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/',
+    '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/',
+    '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/',
+    '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/',
+    '/^(?:(?=.)a[^/]*?[^c])$/',
+    '/^(?:(?=.)a[X-]b)$/',
+    '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/',
+    '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/',
+    '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/',
+    '/^(?:(?=.)a[b]c)$/',
+    '/^(?:(?=.)a[b]c)$/',
+    '/^(?:(?=.)a[^/]c)$/',
+    '/^(?:a\\*c)$/',
+    'false',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/',
+    '/^(?:man\\/man1\\/bash\\.1)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
+    '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[-abc])$/',
+    '/^(?:(?!\\.)(?=.)[abc-])$/',
+    '/^(?:\\\\)$/',
+    '/^(?:(?!\\.)(?=.)[\\\\])$/',
+    '/^(?:(?!\\.)(?=.)[\\[])$/',
+    '/^(?:\\[)$/',
+    '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[\\]])$/',
+    '/^(?:(?!\\.)(?=.)[\\]-])$/',
+    '/^(?:(?!\\.)(?=.)[a-z])$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
+    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
+    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
+    '/^(?:\\[\\])$/',
+    '/^(?:\\[abc)$/',
+    '/^(?:(?=.)XYZ)$/i',
+    '/^(?:(?=.)ab[^/]*?)$/i',
+    '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i',
+    '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/',
+    '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/',
+    '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
+    '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/',
+    '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
+    '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/',
+    '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
+    '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/',
+    '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
+    '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/',
+    '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/',
+    '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/',
+    '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
+    '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/',
+    '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/',
+    '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/',
+    '/^(?:(?=.)a[^/]b)$/',
+    '/^(?:(?=.)#[^/]*?)$/',
+    '/^(?!^(?:(?=.)a[^/]*?)$).*$/',
+    '/^(?:(?=.)\\!a[^/]*?)$/',
+    '/^(?:(?=.)a[^/]*?)$/',
+    '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/',
+    '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/',
+    '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ]
+var re = 0;
+
+tap.test("basic tests", function (t) {
+  var start = Date.now()
+
+  // [ pattern, [matches], MM opts, files, TAP opts]
+  patterns.forEach(function (c) {
+    if (typeof c === "function") return c()
+    if (typeof c === "string") return t.comment(c)
+
+    var pattern = c[0]
+      , expect = c[1].sort(alpha)
+      , options = c[2] || {}
+      , f = c[3] || files
+      , tapOpts = c[4] || {}
+
+    // options.debug = true
+    var m = new mm.Minimatch(pattern, options)
+    var r = m.makeRe()
+    var expectRe = regexps[re++]
+    tapOpts.re = String(r) || JSON.stringify(r)
+    tapOpts.files = JSON.stringify(f)
+    tapOpts.pattern = pattern
+    tapOpts.set = m.set
+    tapOpts.negated = m.negate
+
+    var actual = mm.match(f, pattern, options)
+    actual.sort(alpha)
+
+    t.equivalent( actual, expect
+                , JSON.stringify(pattern) + " " + JSON.stringify(expect)
+                , tapOpts )
+
+    t.equal(tapOpts.re, expectRe, tapOpts)
+  })
+
+  t.comment("time=" + (Date.now() - start) + "ms")
+  t.end()
+})
+
+tap.test("global leak test", function (t) {
+  var globalAfter = Object.keys(global)
+  t.equivalent(globalAfter, globalBefore, "no new globals, please")
+  t.end()
+})
+
+function alpha (a, b) {
+  return a > b ? 1 : -1
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js	(revision 533)
@@ -0,0 +1,33 @@
+var tap = require("tap")
+  , minimatch = require("../")
+
+tap.test("brace expansion", function (t) {
+  // [ pattern, [expanded] ]
+  ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}"
+      , [ "abxy"
+        , "abxz"
+        , "acdxy"
+        , "acdxz"
+        , "acexy"
+        , "acexz"
+        , "afhxy"
+        , "afhxz"
+        , "aghxy"
+        , "aghxz" ] ]
+    , [ "a{1..5}b"
+      , [ "a1b"
+        , "a2b"
+        , "a3b"
+        , "a4b"
+        , "a5b" ] ]
+    , [ "a{b}c", ["a{b}c"] ]
+  ].forEach(function (tc) {
+    var p = tc[0]
+      , expect = tc[1]
+    t.equivalent(minimatch.braceExpand(p), expect, p)
+  })
+  console.error("ending")
+  t.end()
+})
+
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js	(revision 533)
@@ -0,0 +1,14 @@
+var Minimatch = require("../minimatch.js").Minimatch
+var tap = require("tap")
+tap.test("cache test", function (t) {
+  var mm1 = new Minimatch("a?b")
+  var mm2 = new Minimatch("a?b")
+  t.equal(mm1, mm2, "should get the same object")
+  // the lru should drop it after 100 entries
+  for (var i = 0; i < 100; i ++) {
+    new Minimatch("a"+i)
+  }
+  mm2 = new Minimatch("a?b")
+  t.notEqual(mm1, mm2, "cache should have dropped")
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js	(revision 533)
@@ -0,0 +1,274 @@
+// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test
+//
+// TODO: Some of these tests do very bad things with backslashes, and will
+// most likely fail badly on windows.  They should probably be skipped.
+
+var tap = require("tap")
+  , globalBefore = Object.keys(global)
+  , mm = require("../")
+  , files = [ "a", "b", "c", "d", "abc"
+            , "abd", "abe", "bb", "bcd"
+            , "ca", "cb", "dd", "de"
+            , "bdir/", "bdir/cfile"]
+  , next = files.concat([ "a-b", "aXb"
+                        , ".x", ".y" ])
+
+tap.test("basic tests", function (t) {
+  var start = Date.now()
+
+  // [ pattern, [matches], MM opts, files, TAP opts]
+  ; [ "http://www.bashcookbook.com/bashinfo" +
+      "/source/bash-1.14.7/tests/glob-test"
+    , ["a*", ["a", "abc", "abd", "abe"]]
+    , ["X*", ["X*"], {nonull: true}]
+
+    // allow null glob expansion
+    , ["X*", []]
+
+    // isaacs: Slightly different than bash/sh/ksh
+    // \\* is not un-escaped to literal "*" in a failed match,
+    // but it does make it get treated as a literal star
+    , ["\\*", ["\\*"], {nonull: true}]
+    , ["\\**", ["\\**"], {nonull: true}]
+    , ["\\*\\*", ["\\*\\*"], {nonull: true}]
+
+    , ["b*/", ["bdir/"]]
+    , ["c*", ["c", "ca", "cb"]]
+    , ["**", files]
+
+    , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}]
+    , ["s/\\..*//", ["s/\\..*//"], {nonull: true}]
+
+    , "legendary larry crashes bashes"
+    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"
+      , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}]
+    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"
+      , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}]
+
+    , "character classes"
+    , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]]
+    , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd",
+       "bdir/", "ca", "cb", "dd", "de"]]
+    , ["a*[^c]", ["abd", "abe"]]
+    , function () { files.push("a-b", "aXb") }
+    , ["a[X-]b", ["a-b", "aXb"]]
+    , function () { files.push(".x", ".y") }
+    , ["[^a-c]*", ["d", "dd", "de"]]
+    , function () { files.push("a*b/", "a*b/ooo") }
+    , ["a\\*b/*", ["a*b/ooo"]]
+    , ["a\\*?/*", ["a*b/ooo"]]
+    , ["*\\\\!*", [], {null: true}, ["echo !7"]]
+    , ["*\\!*", ["echo !7"], null, ["echo !7"]]
+    , ["*.\\*", ["r.*"], null, ["r.*"]]
+    , ["a[b]c", ["abc"]]
+    , ["a[\\b]c", ["abc"]]
+    , ["a?c", ["abc"]]
+    , ["a\\*c", [], {null: true}, ["abc"]]
+    , ["", [""], { null: true }, [""]]
+
+    , "http://www.opensource.apple.com/source/bash/bash-23/" +
+      "bash/tests/glob-test"
+    , function () { files.push("man/", "man/man1/", "man/man1/bash.1") }
+    , ["*/man*/bash.*", ["man/man1/bash.1"]]
+    , ["man/man1/bash.1", ["man/man1/bash.1"]]
+    , ["a***c", ["abc"], null, ["abc"]]
+    , ["a*****?c", ["abc"], null, ["abc"]]
+    , ["?*****??", ["abc"], null, ["abc"]]
+    , ["*****??", ["abc"], null, ["abc"]]
+    , ["?*****?c", ["abc"], null, ["abc"]]
+    , ["?***?****c", ["abc"], null, ["abc"]]
+    , ["?***?****?", ["abc"], null, ["abc"]]
+    , ["?***?****", ["abc"], null, ["abc"]]
+    , ["*******c", ["abc"], null, ["abc"]]
+    , ["*******?", ["abc"], null, ["abc"]]
+    , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+    , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+    , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+    , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+    , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+    , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]]
+    , ["[-abc]", ["-"], null, ["-"]]
+    , ["[abc-]", ["-"], null, ["-"]]
+    , ["\\", ["\\"], null, ["\\"]]
+    , ["[\\\\]", ["\\"], null, ["\\"]]
+    , ["[[]", ["["], null, ["["]]
+    , ["[", ["["], null, ["["]]
+    , ["[*", ["[abc"], null, ["[abc"]]
+    , "a right bracket shall lose its special meaning and\n" +
+      "represent itself in a bracket expression if it occurs\n" +
+      "first in the list.  -- POSIX.2 2.8.3.2"
+    , ["[]]", ["]"], null, ["]"]]
+    , ["[]-]", ["]"], null, ["]"]]
+    , ["[a-\z]", ["p"], null, ["p"]]
+    , ["??**********?****?", [], { null: true }, ["abc"]]
+    , ["??**********?****c", [], { null: true }, ["abc"]]
+    , ["?************c****?****", [], { null: true }, ["abc"]]
+    , ["*c*?**", [], { null: true }, ["abc"]]
+    , ["a*****c*?**", [], { null: true }, ["abc"]]
+    , ["a********???*******", [], { null: true }, ["abc"]]
+    , ["[]", [], { null: true }, ["a"]]
+    , ["[abc", [], { null: true }, ["["]]
+
+    , "nocase tests"
+    , ["XYZ", ["xYz"], { nocase: true, null: true }
+      , ["xYz", "ABC", "IjK"]]
+    , ["ab*", ["ABC"], { nocase: true, null: true }
+      , ["xYz", "ABC", "IjK"]]
+    , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true }
+      , ["xYz", "ABC", "IjK"]]
+
+    // [ pattern, [matches], MM opts, files, TAP opts]
+    , "onestar/twostar"
+    , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]]
+    , ["{/?,*}", ["/a", "bb"], {null: true}
+      , ["/a", "/b/b", "/a/b/c", "bb"]]
+
+    , "dots should not match unless requested"
+    , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]]
+
+    // .. and . can only match patterns starting with .,
+    // even when options.dot is set.
+    , function () {
+        files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"]
+      }
+    , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}]
+    , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}]
+    , ["a/*/b", ["a/c/b"], {dot:false}]
+    , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}]
+
+
+    // this also tests that changing the options needs
+    // to change the cache key, even if the pattern is
+    // the same!
+    , ["**", ["a/b","a/.d",".a/.d"], { dot: true }
+      , [ ".a/.d", "a/.d", "a/b"]]
+
+    , "paren sets cannot contain slashes"
+    , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]]
+
+    // brace sets trump all else.
+    //
+    // invalid glob pattern.  fails on bash4 and bsdglob.
+    // however, in this implementation, it's easier just
+    // to do the intuitive thing, and let brace-expansion
+    // actually come before parsing any extglob patterns,
+    // like the documentation seems to say.
+    //
+    // XXX: if anyone complains about this, either fix it
+    // or tell them to grow up and stop complaining.
+    //
+    // bash/bsdglob says this:
+    // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]]
+    // but we do this instead:
+    , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]]
+
+    // test partial parsing in the presence of comment/negation chars
+    , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]]
+    , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]]
+
+    // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped.
+    , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g"
+      , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"]
+      , {}
+      , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]]
+
+
+    // crazy nested {,,} and *(||) tests.
+    , function () {
+        files = [ "a", "b", "c", "d"
+                , "ab", "ac", "ad"
+                , "bc", "cb"
+                , "bc,d", "c,db", "c,d"
+                , "d)", "(b|c", "*(b|c"
+                , "b|c", "b|cc", "cb|c"
+                , "x(a|b|c)", "x(a|c)"
+                , "(a|b|c)", "(a|c)"]
+      }
+    , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]]
+    , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]]
+    // a
+    // *(b|c)
+    // *(b|d)
+    , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]]
+    , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]]
+
+
+    // test various flag settings.
+    , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"]
+      , { noext: true } ]
+    , ["a?b", ["x/y/acb", "acb/"], {matchBase: true}
+      , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ]
+    , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]]
+
+
+    // begin channelling Boole and deMorgan...
+    , "negation tests"
+    , function () {
+        files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"]
+      }
+
+    // anything that is NOT a* matches.
+    , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]]
+
+    // anything that IS !a* matches.
+    , ["!a*", ["!ab", "!abc"], {nonegate: true}]
+
+    // anything that IS a* matches
+    , ["!!a*", ["a!b"]]
+
+    // anything that is NOT !a* matches
+    , ["!\\!a*", ["a!b", "d", "e", "\\!a"]]
+
+    // negation nestled within a pattern
+    , function () {
+        files = [ "foo.js"
+                , "foo.bar"
+                // can't match this one without negative lookbehind.
+                , "foo.js.js"
+                , "blar.js"
+                , "foo."
+                , "boo.js.boo" ]
+      }
+    , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
+
+    ].forEach(function (c) {
+      if (typeof c === "function") return c()
+      if (typeof c === "string") return t.comment(c)
+
+      var pattern = c[0]
+        , expect = c[1].sort(alpha)
+        , options = c[2] || {}
+        , f = c[3] || files
+        , tapOpts = c[4] || {}
+
+      // options.debug = true
+      var Class = mm.defaults(options).Minimatch
+      var m = new Class(pattern, {})
+      var r = m.makeRe()
+      tapOpts.re = String(r) || JSON.stringify(r)
+      tapOpts.files = JSON.stringify(f)
+      tapOpts.pattern = pattern
+      tapOpts.set = m.set
+      tapOpts.negated = m.negate
+
+      var actual = mm.match(f, pattern, options)
+      actual.sort(alpha)
+
+      t.equivalent( actual, expect
+                  , JSON.stringify(pattern) + " " + JSON.stringify(expect)
+                  , tapOpts )
+    })
+
+  t.comment("time=" + (Date.now() - start) + "ms")
+  t.end()
+})
+
+tap.test("global leak test", function (t) {
+  var globalAfter = Object.keys(global)
+  t.equivalent(globalAfter, globalBefore, "no new globals, please")
+  t.end()
+})
+
+function alpha (a, b) {
+  return a > b ? 1 : -1
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/extglob-ending-with-state-char.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/extglob-ending-with-state-char.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/extglob-ending-with-state-char.js	(revision 533)
@@ -0,0 +1,8 @@
+var test = require('tap').test
+var minimatch = require('../')
+
+test('extglob ending with statechar', function(t) {
+  t.notOk(minimatch('ax', 'a?(b*)'))
+  t.ok(minimatch('ax', '?(a*|b)'))
+  t.end()
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json	(revision 533)
@@ -0,0 +1,60 @@
+{
+  "name": "globule",
+  "description": "An easy-to-use wildcard globbing library.",
+  "version": "0.1.0",
+  "homepage": "https://github.com/cowboy/node-globule",
+  "author": {
+    "name": "\"Cowboy\" Ben Alman",
+    "url": "http://benalman.com/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/cowboy/node-globule.git"
+  },
+  "bugs": {
+    "url": "https://github.com/cowboy/node-globule/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://github.com/cowboy/node-globule/blob/master/LICENSE-MIT"
+    }
+  ],
+  "main": "lib/globule",
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "grunt nodeunit"
+  },
+  "devDependencies": {
+    "grunt-contrib-jshint": "~0.1.1",
+    "grunt-contrib-nodeunit": "~0.1.2",
+    "grunt-contrib-watch": "~0.2.0",
+    "grunt": "~0.4.1"
+  },
+  "keywords": [
+    "glob",
+    "file",
+    "match",
+    "mapping",
+    "expand",
+    "wildcard",
+    "pattern",
+    "sync",
+    "awesome"
+  ],
+  "dependencies": {
+    "lodash": "~1.0.1",
+    "glob": "~3.1.21",
+    "minimatch": "~0.2.11"
+  },
+  "readme": "# globule [![Build Status](https://secure.travis-ci.org/cowboy/node-globule.png?branch=master)](http://travis-ci.org/cowboy/node-globule)\n\nAn easy-to-use wildcard globbing library.\n\n## Getting Started\nInstall the module with: `npm install globule`\n\n```javascript\nvar globule = require('globule');\nvar filepaths = globule.find('**/*.js');\n```\n\n## Documentation\n\n### globule.find\nReturns a unique array of all file or directory paths that match the given globbing pattern(s). This method accepts either comma separated globbing patterns or an array of globbing patterns. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.\n\n```js\nglobule.find(patterns [, options])\n```\n\nThe `options` object supports all [glob][] library options, along with a few extras. These are the most commonly used:\n\n* `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that will be passed the matched `src` filepath and `options` object as arguments. This function should return a `Boolean` value.\n* `nonull` Retain globbing patterns in result set even if they fail to match files.\n* `matchBase` Patterns without slashes will match just the basename part. Eg. this makes `*.js` work like `**/*.js`.\n* `srcBase` Patterns will be matched relative to the specified path instead of the current working directory. This is a synonym for `cwd`.\n* `prefixBase` Any specified `srcBase` will be prefixed to all returned filepaths.\n\n[glob]: https://github.com/isaacs/node-glob\n\n### globule.match\nMatch one or more globbing patterns against one or more file paths. Returns a uniqued array of all file paths that match any of the specified globbing patterns. Both the `patterns` and `filepaths` arguments can be a single string or array of strings. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.\n\n```js\ngrunt.file.match(patterns, filepaths [, options])\n```\n\n### globule.isMatch\nThis method contains the same signature and logic as the `globule.match` method, but returns `true` if any files were matched, otherwise `false`.\n\n```js\ngrunt.file.isMatch(patterns, filepaths [, options])\n```\n\n### globule.mapping\nGiven a set of source file paths, returns an array of src-dest file mapping objects. Both src and dest paths may be renamed, depending on the options specified.\n\n```js\nglobule.mapping(filepaths [, options])\n```\n\nIn addition to the options the `globule.find` method supports, the options object also supports these properties:\n\n* `srcBase` The directory from which patterns are matched. Any string specified as `srcBase` is effectively stripped from the beginning of all matched paths.\n* `destBase` The specified path is prefixed to all `dest` filepaths.\n* `ext` Remove anything after (and including) the first `.` in the destination path, then append this value.\n* `extDot` Change the behavior of `ext`, `\"first\"` and `\"last\"` will remove anything after the first or last `.` in the destination filename, respectively. Defaults to `\"first\"`.\n* `flatten` Remove the path component from all matched src files. The src file path is still joined to the specified destBase.\n* `rename` If specified, this function will be responsible for returning the final `dest` filepath. By default, it flattens paths (if specified), changes extensions (if specified) and joins the matched path to the `destBase`.\n\n### globule.findMapping\nThis method is a convenience wrapper around the `globule.find` and `globule.mapping` methods.\n\n```js\nglobule.findMapping(patterns [, options])\n```\n\n\n## Examples\n\nGiven the files `foo/a.js` and `foo/b.js`:\n\n### srcBase and destBase\n\n```js\nglobule.find(\"foo/*.js\")\n// [\"foo/a.js\", \"foo/b.js\"]\n\nglobule.find(\"*.js\", {srcBase: \"foo\"})\n// [\"a.js\", \"b.js\"]\n\nglobule.find(\"*.js\", {srcBase: \"foo\", prefixBase: true})\n// [\"foo/a.js\", \"foo/b.js\"]\n```\n\n```js\nglobule.findMapping(\"foo/*.js\")\n// [{src: \"foo/a.js\", dest: \"foo/a.js\"}, {src: \"foo/b.js\", dest: \"foo/b.js\"}]\n\nglobule.findMapping(\"foo/*.js\", {destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/foo/a.js\"}, {src: \"foo/b.js\", dest: \"bar/foo/b.js\"}]\n\nglobule.findMapping(\"*.js\", {srcBase: \"foo\", destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/a.js\"}, {src: \"foo/b.js\", dest: \"bar/b.js\"}]\n```\n\n```js\nglobule.mapping([\"foo/a.js\", \"foo/b.js\"])\n// [{src: \"foo/a.js\", dest: \"foo/a.js\"}, {src: \"foo/b.js\", dest: \"foo/b.js\"}]\n\nglobule.mapping([\"foo/a.js\", \"foo/b.js\"], {destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/foo/a.js\"}, {src: \"foo/b.js\", dest: \"bar/foo/b.js\"}]\n\nglobule.mapping([\"a.js\", \"b.js\"], {srcBase: \"foo\", destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/a.js\"}, {src: \"foo/b.js\", dest: \"bar/b.js\"}]\n```\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).\n\n## Release History\n_(Nothing yet)_\n\n## License\nCopyright (c) 2013 \"Cowboy\" Ben Alman  \nLicensed under the MIT license.\n",
+  "readmeFilename": "README.md",
+  "_id": "globule@0.1.0",
+  "dist": {
+    "shasum": "56bb043ce2102a849b99c1559bf3fba516dcb21c"
+  },
+  "_from": "globule@~0.1.0",
+  "_resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js	(revision 533)
@@ -0,0 +1,486 @@
+'use strict';
+
+var path = require('path');
+
+var globule = require('../lib/globule.js');
+
+/*
+  ======== A Handy Little Nodeunit Reference ========
+  https://github.com/caolan/nodeunit
+
+  Test methods:
+    test.expect(numAssertions)
+    test.done()
+  Test assertions:
+    test.ok(value, [message])
+    test.equal(actual, expected, [message])
+    test.notEqual(actual, expected, [message])
+    test.deepEqual(actual, expected, [message])
+    test.notDeepEqual(actual, expected, [message])
+    test.strictEqual(actual, expected, [message])
+    test.notStrictEqual(actual, expected, [message])
+    test.throws(block, [error], [message])
+    test.doesNotThrow(block, [error], [message])
+    test.ifError(value)
+*/
+
+exports['match'] = {
+  'empty set': function(test) {
+    test.expect(6);
+    // Should return empty set if a required argument is missing or an empty set.
+    test.deepEqual(globule.match(null, 'foo.js'), [], 'should return empty set.');
+    test.deepEqual(globule.match('*.js', null), [], 'should return empty set.');
+    test.deepEqual(globule.match([], 'foo.js'), [], 'should return empty set.');
+    test.deepEqual(globule.match('*.js', []), [], 'should return empty set.');
+    test.deepEqual(globule.match(null, ['foo.js']), [], 'should return empty set.');
+    test.deepEqual(globule.match(['*.js'], null), [], 'should return empty set.');
+    test.done();
+  },
+  'basic matching': function(test) {
+    test.expect(6);
+    test.deepEqual(globule.match('*.js', 'foo.js'), ['foo.js'], 'should match correctly.');
+    test.deepEqual(globule.match('*.js', ['foo.js']), ['foo.js'], 'should match correctly.');
+    test.deepEqual(globule.match('*.js', ['foo.js', 'bar.css']), ['foo.js'], 'should match correctly.');
+    test.deepEqual(globule.match(['*.js', '*.css'], 'foo.js'), ['foo.js'], 'should match correctly.');
+    test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js']), ['foo.js'], 'should match correctly.');
+    test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js', 'bar.css']), ['foo.js', 'bar.css'], 'should match correctly.');
+    test.done();
+  },
+  'no matches': function(test) {
+    test.expect(2);
+    test.deepEqual(globule.match('*.js', 'foo.css'), [], 'should fail to match.');
+    test.deepEqual(globule.match('*.js', ['foo.css', 'bar.css']), [], 'should fail to match.');
+    test.done();
+  },
+  'unique': function(test) {
+    test.expect(2);
+    test.deepEqual(globule.match('*.js', ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.');
+    test.deepEqual(globule.match(['*.js', '*.*'], ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.');
+    test.done();
+  },
+  'flatten': function(test) {
+    test.expect(1);
+    test.deepEqual(globule.match([['*.js', '*.css'], ['*.*', '*.js']], ['foo.js', 'bar.css']),
+      ['foo.js', 'bar.css'],
+      'should process nested pattern arrays correctly.');
+    test.done();
+  },
+  'exclusion': function(test) {
+    test.expect(5);
+    test.deepEqual(globule.match(['!*.js'], ['foo.js', 'bar.js']), [], 'solitary exclusion should match nothing');
+    test.deepEqual(globule.match(['*.js', '!*.js'], ['foo.js', 'bar.js']), [], 'exclusion should cancel match');
+    test.deepEqual(globule.match(['*.js', '!f*.js'], ['foo.js', 'bar.js', 'baz.js']),
+      ['bar.js', 'baz.js'],
+      'partial exclusion should partially cancel match');
+    test.deepEqual(globule.match(['*.js', '!*.js', 'b*.js'], ['foo.js', 'bar.js', 'baz.js']),
+      ['bar.js', 'baz.js'],
+      'inclusion / exclusion order matters');
+    test.deepEqual(globule.match(['*.js', '!f*.js', '*.js'], ['foo.js', 'bar.js', 'baz.js']),
+      ['bar.js', 'baz.js', 'foo.js'],
+      'inclusion / exclusion order matters');
+    test.done();
+  },
+  'options.matchBase': function(test) {
+    test.expect(2);
+    test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js'], {matchBase: true}),
+      ['foo.js', 'baz/xyz.js'],
+      'should matchBase (minimatch) when specified.');
+    test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js']),
+      ['foo.js'],
+      'should not matchBase (minimatch) by default.');
+    test.done();
+  },
+};
+
+exports['isMatch'] = {
+  'basic matching': function(test) {
+    test.expect(6);
+    test.ok(globule.isMatch('*.js', 'foo.js'), 'should match correctly.');
+    test.ok(globule.isMatch('*.js', ['foo.js']), 'should match correctly.');
+    test.ok(globule.isMatch('*.js', ['foo.js', 'bar.css']), 'should match correctly.');
+    test.ok(globule.isMatch(['*.js', '*.css'], 'foo.js'), 'should match correctly.');
+    test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js']), 'should match correctly.');
+    test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js', 'bar.css']), 'should match correctly.');
+    test.done();
+  },
+  'no matches': function(test) {
+    test.expect(6);
+    test.ok(!globule.isMatch('*.js', 'foo.css'), 'should fail to match.');
+    test.ok(!globule.isMatch('*.js', ['foo.css', 'bar.css']), 'should fail to match.');
+    test.ok(!globule.isMatch(null, 'foo.css'), 'should fail to match.');
+    test.ok(!globule.isMatch('*.js', null), 'should fail to match.');
+    test.ok(!globule.isMatch([], 'foo.css'), 'should fail to match.');
+    test.ok(!globule.isMatch('*.js', []), 'should fail to match.');
+    test.done();
+  },
+  'options.matchBase': function(test) {
+    test.expect(2);
+    test.ok(globule.isMatch('*.js', ['baz/xyz.js'], {matchBase: true}), 'should matchBase (minimatch) when specified.');
+    test.ok(!globule.isMatch('*.js', ['baz/xyz.js']), 'should not matchBase (minimatch) by default.');
+    test.done();
+  },
+};
+
+exports['find'] = {
+  setUp: function(done) {
+    this.cwd = process.cwd();
+    process.chdir('test/fixtures/expand');
+    done();
+  },
+  tearDown: function(done) {
+    process.chdir(this.cwd);
+    done();
+  },
+  'basic matching': function(test) {
+    test.expect(5);
+    test.deepEqual(globule.find('**/*.js'), ['js/bar.js', 'js/foo.js'], 'single pattern argument should match.');
+    test.deepEqual(globule.find('**/*.js', '**/*.css'),
+      ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
+      'multiple pattern arguments should match.');
+    test.deepEqual(globule.find(['**/*.js', '**/*.css']),
+      ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
+      'array of patterns should match.');
+    test.deepEqual(globule.find([['**/*.js'], [['**/*.css', 'js/*.js']]]),
+      ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
+      'array of arrays of patterns should be flattened.');
+    test.deepEqual(globule.find('*.xyz'), [], 'bad pattern should fail to match.');
+    test.done();
+  },
+  'unique': function(test) {
+    test.expect(4);
+    test.deepEqual(globule.find('**/*.js', 'js/*.js'),
+      ['js/bar.js', 'js/foo.js'],
+      'file list should be uniqed.');
+    test.deepEqual(globule.find('**/*.js', '**/*.css', 'js/*.js'), ['js/bar.js', 'js/foo.js',
+      'css/baz.css', 'css/qux.css'],
+      'file list should be uniqed.');
+    test.deepEqual(globule.find('js', 'js/'),
+      ['js', 'js/'],
+      'mixed non-ending-/ and ending-/ dirs will not be uniqed by default.');
+    test.deepEqual(globule.find('js', 'js/', {mark: true}),
+      ['js/'],
+      'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.');
+    test.done();
+  },
+  'file order': function(test) {
+    test.expect(5);
+    var actual = globule.find('**/*.{js,css}');
+    var expected = ['css/baz.css', 'css/qux.css', 'js/bar.js', 'js/foo.js'];
+    test.deepEqual(actual, expected, 'should select 4 files in this order, by default.');
+
+    actual = globule.find('js/foo.js', 'js/bar.js', '**/*.{js,css}');
+    expected = ['js/foo.js', 'js/bar.js', 'css/baz.css', 'css/qux.css'];
+    test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
+
+    actual = globule.find('js/bar.js', 'js/foo.js', '**/*.{js,css}');
+    expected = ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'];
+    test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
+
+    actual = globule.find('**/*.{js,css}', '!css/qux.css', 'css/qux.css');
+    expected = ['css/baz.css', 'js/bar.js', 'js/foo.js', 'css/qux.css'];
+    test.deepEqual(actual, expected, 'if a file is excluded and then re-added, it should be added at the end.');
+
+    actual = globule.find('js/foo.js', '**/*.{js,css}', '!css/qux.css', 'css/qux.css');
+    expected = ['js/foo.js', 'css/baz.css', 'js/bar.js', 'css/qux.css'];
+    test.deepEqual(actual, expected, 'should be able to combine specified-up-front and excluded/added-at-end.');
+    test.done();
+  },
+  'exclusion': function(test) {
+    test.expect(8);
+    test.deepEqual(globule.find(['!js/*.js']), [], 'solitary exclusion should match nothing');
+    test.deepEqual(globule.find(['js/bar.js','!js/bar.js']), [], 'exclusion should negate match');
+    test.deepEqual(globule.find(['**/*.js', '!js/foo.js']),
+      ['js/bar.js'],
+      'should omit single file from matched set');
+    test.deepEqual(globule.find(['!js/foo.js', '**/*.js']),
+      ['js/bar.js', 'js/foo.js'],
+      'inclusion / exclusion order matters');
+    test.deepEqual(globule.find(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']),
+      ['js/foo.js','css/qux.css'],
+      'multiple exclusions should be removed from the set');
+    test.deepEqual(globule.find(['**/*.js', '**/*.css', '!**/*.css']),
+      ['js/bar.js', 'js/foo.js'],
+      'excluded wildcards should be removed from the matched set');
+    test.deepEqual(globule.find(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']),
+      ['js/foo.js', 'css/qux.css'],
+      'different pattern for exclusion should still work');
+    test.deepEqual(globule.find(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']),
+      ['js/foo.js', 'css/baz.css', 'css/qux.css'],
+      'inclusion / exclusion order matters');
+    test.done();
+  },
+  'options.mark': function(test) {
+    test.expect(4);
+    test.deepEqual(globule.find('**d*/**'), [
+      'deep',
+      'deep/deep.txt',
+      'deep/deeper',
+      'deep/deeper/deeper.txt',
+      'deep/deeper/deepest',
+      'deep/deeper/deepest/deepest.txt'], 'should match files and directories.');
+    test.deepEqual(globule.find('**d*/**/'), [
+      'deep/',
+      'deep/deeper/',
+      'deep/deeper/deepest/'], 'trailing / in pattern should match directories only, matches end in /.');
+    test.deepEqual(globule.find('**d*/**', {mark: true}), [
+      'deep/',
+      'deep/deep.txt',
+      'deep/deeper/',
+      'deep/deeper/deeper.txt',
+      'deep/deeper/deepest/',
+      'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.');
+    test.deepEqual(globule.find('**d*/**/', {mark: true}), [
+      'deep/',
+      'deep/deeper/',
+      'deep/deeper/deepest/'], 'the minimatch "mark" option should not remove trailing / from matched paths.');
+    test.done();
+  },
+  'options.filter': function(test) {
+    test.expect(5);
+    test.deepEqual(globule.find('**d*/**', {filter: 'isFile'}), [
+      'deep/deep.txt',
+      'deep/deeper/deeper.txt',
+      'deep/deeper/deepest/deepest.txt'
+    ], 'should match files only.');
+    test.deepEqual(globule.find('**d*/**', {filter: 'isDirectory'}), [
+      'deep',
+      'deep/deeper',
+      'deep/deeper/deepest'
+    ], 'should match directories only.');
+    test.deepEqual(globule.find('**', {
+      arbitraryProp: /deepest/,
+      filter: function(filepath, options) {
+        return options.arbitraryProp.test(filepath);
+      }
+    }), [
+      'deep/deeper/deepest',
+      'deep/deeper/deepest/deepest.txt',
+    ], 'should filter arbitrarily.');
+    test.deepEqual(globule.find('js', 'css', {filter: 'isFile'}), [], 'should fail to match.');
+    test.deepEqual(globule.find('**/*.js', {filter: 'isDirectory'}), [], 'should fail to match.');
+    test.done();
+  },
+  'options.matchBase': function(test) {
+    test.expect(3);
+    test.deepEqual(globule.find('*.js'), [], 'should not matchBase (minimatch) by default.');
+    test.deepEqual(globule.find('*.js', {matchBase: true}),
+      ['js/bar.js', 'js/foo.js'],
+      'matchBase option should be passed through to minimatch.');
+    test.deepEqual(globule.find('*.js', '*.css', {matchBase: true}),
+      ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
+      'matchBase option should be passed through to minimatch.');
+    test.done();
+  },
+  'options.srcBase': function(test) {
+    test.expect(5);
+    test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep'}),
+      ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
+      'should find paths matching pattern relative to srcBase.');
+    test.deepEqual(globule.find(['**/deep*.txt'], {cwd: 'deep'}),
+      ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
+      'cwd and srcBase should do the same thing.');
+    test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isFile'}),
+      ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
+      'srcBase should not prevent filtering.');
+    test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isDirectory'}),
+      ['deeper', 'deeper/deepest'],
+      'srcBase should not prevent filtering.');
+    test.deepEqual(globule.find(['**/deep*.txt', '!**/deeper**'], {srcBase: 'deep'}),
+      ['deep.txt', 'deeper/deepest/deepest.txt'],
+      'srcBase should not prevent exclusions.');
+    test.done();
+  },
+  'options.prefixBase': function(test) {
+    test.expect(2);
+    test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: false}),
+      ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
+      'should not prefix srcBase to returned paths.');
+    test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: true}),
+      ['deep/deep.txt', 'deep/deeper/deeper.txt', 'deep/deeper/deepest/deepest.txt'],
+      'should prefix srcBase to returned paths.');
+    test.done();
+  },
+  'options.nonull': function(test) {
+    test.expect(3);
+    test.deepEqual(globule.find(['*omg*'], {nonull: true}),
+      ['*omg*'],
+      'non-matching patterns should be returned in result set.');
+    test.deepEqual(globule.find(['js/a*', 'js/b*', 'js/c*'], {nonull: true}),
+      ['js/a*', 'js/bar.js', 'js/c*'],
+      'non-matching patterns should be returned in result set.');
+    test.deepEqual(globule.find(['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], {nonull: true}),
+      ['js/foo.js', 'js/bar.js', 'js/nonexistent.js'],
+      'non-matching filenames should be returned in result set.');
+    test.done();
+  },
+};
+
+exports['mapping'] = {
+  'basic mapping': function(test) {
+    test.expect(1);
+
+    var actual = globule.mapping(['a.txt', 'b.txt', 'c.txt']);
+    var expected = [
+      {dest: 'a.txt', src: ['a.txt']},
+      {dest: 'b.txt', src: ['b.txt']},
+      {dest: 'c.txt', src: ['c.txt']},
+    ];
+    test.deepEqual(actual, expected, 'default options should create same-to-same src-dest mappings.');
+
+    test.done();
+  },
+  'options.srcBase': function(test) {
+    test.expect(2);
+    var actual, expected;
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo'});
+    expected = [
+      {dest: 'a.txt', src: ['foo/a.txt']},
+      {dest: 'bar/b.txt', src: ['foo/bar/b.txt']},
+      {dest: 'bar/baz/c.txt', src: ['foo/bar/baz/c.txt']},
+    ];
+    test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (no trailing /).');
+
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo/'});
+    test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (trailing /).');
+
+    test.done();
+  },
+  'options.destBase': function(test) {
+    test.expect(2);
+    var actual, expected;
+
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest'});
+    expected = [
+      {dest: 'dest/a.txt', src: ['a.txt']},
+      {dest: 'dest/bar/b.txt', src: ['bar/b.txt']},
+      {dest: 'dest/bar/baz/c.txt', src: ['bar/baz/c.txt']},
+    ];
+    test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (no trailing /).');
+
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest/'});
+    test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (trailing /).');
+
+    test.done();
+  },
+  'options.flatten': function(test) {
+    test.expect(1);
+    var actual, expected;
+
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {flatten: true});
+    expected = [
+      {dest: 'a.txt', src: ['a.txt']},
+      {dest: 'b.txt', src: ['bar/b.txt']},
+      {dest: 'c.txt', src: ['bar/baz/c.txt']},
+    ];
+    test.deepEqual(actual, expected, 'flatten should remove all src path parts from dest.');
+
+    test.done();
+  },
+  'options.flatten + options.destBase': function(test) {
+    test.expect(1);
+    var actual, expected;
+
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest', flatten: true});
+    expected = [
+      {dest: 'dest/a.txt', src: ['a.txt']},
+      {dest: 'dest/b.txt', src: ['bar/b.txt']},
+      {dest: 'dest/c.txt', src: ['bar/baz/c.txt']},
+    ];
+    test.deepEqual(actual, expected, 'flatten and destBase should work together.');
+
+    test.done();
+  },
+  'options.ext': function(test) {
+    test.expect(1);
+    var actual, expected;
+
+    actual = globule.mapping(['x/a.js', 'x.y/b.min.js', 'x.y/z.z/c'], {ext: '.foo'});
+    expected = [
+      {dest: 'x/a.foo', src: ['x/a.js']},
+      {dest: 'x.y/b.foo', src: ['x.y/b.min.js']},
+      {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
+    ];
+    test.deepEqual(actual, expected, 'by default, ext should replace everything after the first dot in the filename.');
+
+    test.done();
+  },
+  'options.extDot': function(test) {
+    test.expect(2);
+    var actual, expected;
+
+    actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'first'});
+    expected = [
+      {dest: 'x/a.foo', src: ['x/a.js']},
+      {dest: 'x.y/b.foo', src: ['x.y/b.bbb.min.js']},
+      {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
+    ];
+    test.deepEqual(actual, expected, 'extDot of "first" should replace everything after the first dot in the filename.');
+
+    actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'last'});
+    expected = [
+      {dest: 'x/a.foo', src: ['x/a.js']},
+      {dest: 'x.y/b.bbb.min.foo', src: ['x.y/b.bbb.min.js']},
+      {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
+    ];
+    test.deepEqual(actual, expected, 'extDot of "last" should replace everything after the last dot in the filename.');
+
+    test.done();
+  },
+  'options.rename': function(test) {
+    test.expect(1);
+    var actual, expected;
+    actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {
+      arbitraryProp: 'FOO',
+      rename: function(dest, options) {
+        return path.join(options.arbitraryProp, dest.toUpperCase());
+      }
+    });
+    expected = [
+      {dest: 'FOO/A.TXT', src: ['a.txt']},
+      {dest: 'FOO/BAR/B.TXT', src: ['bar/b.txt']},
+      {dest: 'FOO/BAR/BAZ/C.TXT', src: ['bar/baz/c.txt']},
+    ];
+    test.deepEqual(actual, expected, 'allow arbitrary renaming of files.');
+
+    test.done();
+  },
+};
+
+exports['findMapping'] = {
+  setUp: function(done) {
+    this.cwd = process.cwd();
+    process.chdir('test/fixtures');
+    done();
+  },
+  tearDown: function(done) {
+    process.chdir(this.cwd);
+    done();
+  },
+  'basic matching': function(test) {
+    test.expect(2);
+
+    var actual = globule.findMapping(['expand/**/*.txt']);
+    var expected = [
+      {dest: 'expand/deep/deep.txt', src: ['expand/deep/deep.txt']},
+      {dest: 'expand/deep/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
+      {dest: 'expand/deep/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
+    ];
+    test.deepEqual(actual, expected, 'default options');
+
+    expected = globule.mapping(globule.find(['expand/**/*.txt']));
+    test.deepEqual(actual, expected, 'this is what it\'s doing under the hood, anwyays.');
+
+    test.done();
+  },
+  'options.srcBase': function(test) {
+    test.expect(1);
+    var actual = globule.findMapping(['**/*.txt'], {destBase: 'dest', srcBase: 'expand/deep'});
+    var expected = [
+      {dest: 'dest/deep.txt', src: ['expand/deep/deep.txt']},
+      {dest: 'dest/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
+      {dest: 'dest/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
+    ];
+    test.deepEqual(actual, expected, 'srcBase should be stripped from front of destPath, pre-destBase+destPath join');
+    test.done();
+  },
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/gaze/package.json	(revision 533)
@@ -0,0 +1,58 @@
+{
+  "name": "gaze",
+  "description": "A globbing fs.watch wrapper built from the best parts of other fine watch libs.",
+  "version": "0.5.1",
+  "homepage": "https://github.com/shama/gaze",
+  "author": {
+    "name": "Kyle Robinson Young",
+    "email": "kyle@dontkry.com"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/shama/gaze.git"
+  },
+  "bugs": {
+    "url": "https://github.com/shama/gaze/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://github.com/shama/gaze/blob/master/LICENSE-MIT"
+    }
+  ],
+  "main": "lib/gaze",
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "grunt nodeunit -v"
+  },
+  "dependencies": {
+    "globule": "~0.1.0"
+  },
+  "devDependencies": {
+    "grunt": "~0.4.1",
+    "grunt-contrib-nodeunit": "~0.2.0",
+    "grunt-contrib-jshint": "~0.6.0",
+    "grunt-benchmark": "~0.2.0",
+    "grunt-cli": "~0.1.13",
+    "async": "~0.2.10",
+    "rimraf": "~2.2.6"
+  },
+  "keywords": [
+    "watch",
+    "glob"
+  ],
+  "files": [
+    "lib",
+    "LICENSE-MIT"
+  ],
+  "readme": "# gaze [![Build Status](https://travis-ci.org/shama/gaze.png?branch=master)](https://travis-ci.org/shama/gaze)\n\nA globbing fs.watch wrapper built from the best parts of other fine watch libs.  \nCompatible with Node.js 0.10/0.8, Windows, OSX and Linux.\n\n![gaze](http://dontkry.com/images/repos/gaze.png)\n\n## Usage\nInstall the module with: `npm install gaze` or place into your `package.json`\nand run `npm install`.\n\n```javascript\nvar gaze = require('gaze');\n\n// Watch all .js files/dirs in process.cwd()\ngaze('**/*.js', function(err, watcher) {\n  // Files have all started watching\n  // watcher === this\n\n  // Get all watched files\n  console.log(this.watched());\n\n  // On file changed\n  this.on('changed', function(filepath) {\n    console.log(filepath + ' was changed');\n  });\n\n  // On file added\n  this.on('added', function(filepath) {\n    console.log(filepath + ' was added');\n  });\n\n  // On file deleted\n  this.on('deleted', function(filepath) {\n    console.log(filepath + ' was deleted');\n  });\n\n  // On changed/added/deleted\n  this.on('all', function(event, filepath) {\n    console.log(filepath + ' was ' + event);\n  });\n\n  // Get watched files with relative paths\n  console.log(this.relative());\n});\n\n// Also accepts an array of patterns\ngaze(['stylesheets/*.css', 'images/**/*.png'], function() {\n  // Add more patterns later to be watched\n  this.add(['js/*.js']);\n});\n```\n\n### Alternate Interface\n\n```javascript\nvar Gaze = require('gaze').Gaze;\n\nvar gaze = new Gaze('**/*');\n\n// Files have all started watching\ngaze.on('ready', function(watcher) { });\n\n// A file has been added/changed/deleted has occurred\ngaze.on('all', function(event, filepath) { });\n```\n\n### Errors\n\n```javascript\ngaze('**/*', function() {\n  this.on('error', function(err) {\n    // Handle error here\n  });\n});\n```\n\n### Minimatch / Glob\n\nSee [isaacs's minimatch](https://github.com/isaacs/minimatch) for more\ninformation on glob patterns.\n\n## Documentation\n\n### gaze(patterns, [options], callback)\n\n* `patterns` {String|Array} File patterns to be matched\n* `options` {Object}\n* `callback` {Function}\n  * `err` {Error | null}\n  * `watcher` {Object} Instance of the Gaze watcher\n\n### Class: gaze.Gaze\n\nCreate a Gaze object by instanting the `gaze.Gaze` class.\n\n```javascript\nvar Gaze = require('gaze').Gaze;\nvar gaze = new Gaze(pattern, options, callback);\n```\n\n#### Properties\n\n* `options` The options object passed in.\n  * `interval` {integer} Interval to pass to fs.watchFile\n  * `debounceDelay` {integer} Delay for events called in succession for the same\n    file/event\n\n#### Events\n\n* `ready(watcher)` When files have been globbed and watching has begun.\n* `all(event, filepath)` When an `added`, `changed` or `deleted` event occurs.\n* `added(filepath)` When a file has been added to a watch directory.\n* `changed(filepath)` When a file has been changed.\n* `deleted(filepath)` When a file has been deleted.\n* `renamed(newPath, oldPath)` When a file has been renamed.\n* `end()` When the watcher is closed and watches have been removed.\n* `error(err)` When an error occurs.\n* `nomatch` When no files have been matched.\n\n#### Methods\n\n* `emit(event, [...])` Wrapper for the EventEmitter.emit.\n  `added`|`changed`|`deleted` events will also trigger the `all` event.\n* `close()` Unwatch all files and reset the watch instance.\n* `add(patterns, callback)` Adds file(s) patterns to be watched.\n* `remove(filepath)` removes a file or directory from being watched. Does not\n  recurse directories.\n* `watched()` Returns the currently watched files.\n* `relative([dir, unixify])` Returns the currently watched files with relative paths.\n  * `dir` {string} Only return relative files for this directory.\n  * `unixify` {boolean} Return paths with `/` instead of `\\\\` if on Windows.\n\n## FAQs\n\n### Why Another `fs.watch` Wrapper?\nI liked parts of other `fs.watch` wrappers but none had all the features I\nneeded. This lib combines the features I needed from other fine watch libs:\nSpeedy data behavior from\n[paulmillr's chokidar](https://github.com/paulmillr/chokidar), API interface\nfrom [mikeal's watch](https://github.com/mikeal/watch) and file globbing using\n[isaacs's glob](https://github.com/isaacs/node-glob) which is also used by\n[cowboy's Grunt](https://github.com/gruntjs/grunt).\n\n### How do I fix the error `EMFILE: Too many opened files.`?\nThis is because of your system's max opened file limit. For OSX the default is\nvery low (256). Increase your limit temporarily with `ulimit -n 10480`, the\nnumber being the new max limit.\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style.\nAdd unit tests for any new or changed functionality. Lint and test your code\nusing [grunt](http://gruntjs.com/).\n\n## Release History\n* 0.5.1 - Use setImmediate (process.nextTick for node v0.8) to defer ready/nomatch events (@amasad).\n* 0.5.0 - Process is now kept alive while watching files. Emits a nomatch event when no files are matching.\n* 0.4.3 - Track file additions in newly created folders (@brett-shwom).\n* 0.4.2 - Fix .remove() method to remove a single file in a directory (@kaelzhang). Fixing Cannot call method 'call' of undefined (@krasimir). Track new file additions within folders (@brett-shwom).\n* 0.4.1 - Fix watchDir not respecting close in race condition (@chrisirhc).\n* 0.4.0 - Drop support for node v0.6. Use globule for file matching. Avoid node v0.10 path.resolve/join errors. Register new files when added to non-existent folder. Multiple instances can now poll the same files (@jpommerening).\n* 0.3.4 - Code clean up. Fix path must be strings errors (@groner). Fix incorrect added events (@groner).\n* 0.3.3 - Fix for multiple patterns with negate.\n* 0.3.2 - Emit `end` before removeAllListeners.\n* 0.3.1 - Fix added events within subfolder patterns.\n* 0.3.0 - Handle safewrite events, `forceWatchMethod` option removed, bug fixes and watch optimizations (@rgaskill).\n* 0.2.2 - Fix issue where subsequent add calls dont get watched (@samcday). removeAllListeners on close.\n* 0.2.1 - Fix issue with invalid `added` events in current working dir.\n* 0.2.0 - Support and mark folders with `path.sep`. Add `forceWatchMethod` option. Support `renamed` events.\n* 0.1.6 - Recognize the `cwd` option properly\n* 0.1.5 - Catch too many open file errors\n* 0.1.4 - Really fix the race condition with 2 watches\n* 0.1.3 - Fix race condition with 2 watches\n* 0.1.2 - Read triggering changed event fix\n* 0.1.1 - Minor fixes\n* 0.1.0 - Initial release\n\n## License\nCopyright (c) 2013 Kyle Robinson Young  \nLicensed under the MIT license.\n",
+  "readmeFilename": "README.md",
+  "_id": "gaze@0.5.1",
+  "dist": {
+    "shasum": "b250092e4dd26ff0e95ce4b921a1aef308b3eb72"
+  },
+  "_from": "gaze@~0.5.1",
+  "_resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/LICENSE.txt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/LICENSE.txt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/LICENSE.txt	(revision 533)
@@ -0,0 +1,22 @@
+Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+Based on Underscore.js 1.5.2, copyright 2009-2013 Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/README.md	(revision 533)
@@ -0,0 +1,163 @@
+# Lo-Dash v2.4.1
+A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features).
+
+## Download
+
+Check out our [wiki]([https://github.com/lodash/lodash/wiki/build-differences]) for details over the differences between builds.
+
+* Modern builds perfect for newer browsers/environments:<br>
+[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) &
+[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js)
+
+* Compatibility builds for older environment support too:<br>
+[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) &
+[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js)
+
+* Underscore builds to use as a drop-in replacement:<br>
+[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) &
+[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js)
+
+CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash). For smaller file sizes, create [custom builds](http://lodash.com/custom-builds) with only the features needed.
+
+Love modules? Weâve got you covered with [lodash-amd](https://npmjs.org/package/lodash-amd), [lodash-es6](https://github.com/lodash/lodash-es6), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method.
+
+## Dive in
+
+Thereâs plenty of **[documentation](http://lodash.com/docs)**, [unit tests](http://lodash.com/tests), & [benchmarks](http://lodash.com/benchmarks).<br>
+Check out <a href="http://devdocs.io/lodash/">DevDocs</a> as a fast, organized, & searchable interface for our documentation.
+
+The full changelog for this release is available on our [wiki](https://github.com/lodash/lodash/wiki/Changelog).<br>
+A list of upcoming features is available on our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap).
+
+## Features *not* in Underscore
+
+ * AMD loader support ([curl](https://github.com/cujojs/curl), [dojo](http://dojotoolkit.org/), [requirejs](http://requirejs.org/), etc.)
+ * [_(âŠ)](http://lodash.com/docs#_) supports intuitive chaining
+ * [_.at](http://lodash.com/docs#at) for cherry-picking collection values
+ * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*âlazyâ*](http://michaux.ca/articles/lazy-function-definition-pattern) defined methods
+ * [_.clone](http://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects
+ * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects
+ * [_.constant](http://lodash.com/docs#constant) & [_.property](http://lodash.com/docs#property) function generators for composing functions
+ * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex`
+ * [_.create](http://lodash.com/docs#create) for easier object inheritance
+ * [_.createCallback](http://lodash.com/docs#createCallback) for extending callbacks in methods & mixins
+ * [_.curry](http://lodash.com/docs#curry) for creating [curried](http://hughfdjackson.com/javascript/2013/07/06/why-curry-helps/) functions
+ * [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) accept additional `options` for more control
+ * [_.findIndex](http://lodash.com/docs#findIndex) & [_.findKey](http://lodash.com/docs#findKey) for finding indexes & keys
+ * [_.forEach](http://lodash.com/docs#forEach) is chainable & supports exiting early
+ * [_.forIn](http://lodash.com/docs#forIn) for iterating own & inherited properties
+ * [_.forOwn](http://lodash.com/docs#forOwn) for iterating own properties
+ * [_.isPlainObject](http://lodash.com/docs#isPlainObject) for checking if values are created by `Object`
+ * [_.mapValues](http://lodash.com/docs#mapValues) for [mapping](http://lodash.com/docs#map) values to an object
+ * [_.memoize](http://lodash.com/docs#memoize) exposes the `cache` of memoized functions
+ * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
+ * [_.noop](http://lodash.com/docs#noop) for function placeholders
+ * [_.now](http://lodash.com/docs#now) as a cross-browser `Date.now` alternative
+ * [_.parseInt](http://lodash.com/docs#parseInt) for consistent behavior
+ * [_.pull](http://lodash.com/docs#pull) & [_.remove](http://lodash.com/docs#remove) for mutating arrays
+ * [_.random](http://lodash.com/docs#random) supports returning floating-point numbers
+ * [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking
+ * [_.sortBy](http://lodash.com/docs#sortBy) supports sorting by multiple properties
+ * [_.support](http://lodash.com/docs#support) for flagging environment features
+ * [_.template](http://lodash.com/docs#template) supports [*âimportsâ*](http://lodash.com/docs#templateSettings_imports) options & [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals)
+ * [_.transform](http://lodash.com/docs#transform) as a powerful alternative to [_.reduce](http://lodash.com/docs#reduce) for transforming objects
+ * [_.where](http://lodash.com/docs#where) supports deep object comparisons
+ * [_.xor](http://lodash.com/docs#xor) as a companion to [_.difference](http://lodash.com/docs#difference), [_.intersection](http://lodash.com/docs#intersection), & [_.union](http://lodash.com/docs#union)
+ * [_.zip](http://lodash.com/docs#zip) is capable of unzipping values
+ * [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick), &
+   [more](http://lodash.com/docs "_.assign, _.clone, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept callbacks
+ * [_.contains](http://lodash.com/docs#contains), [_.toArray](http://lodash.com/docs#toArray), &
+   [more](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.forEachRight, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.size, _.some, _.sortBy, _.where") accept strings
+ * [_.filter](http://lodash.com/docs#filter), [_.map](http://lodash.com/docs#map), &
+   [more](http://lodash.com/docs "_.countBy, _.every, _.find, _.findKey, _.findLast, _.findLastIndex, _.findLastKey, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *â_.pluckâ* & *â_.whereâ* shorthands
+ * [_.findLast](http://lodash.com/docs#findLast), [_.findLastIndex](http://lodash.com/docs#findLastIndex), &
+   [more](http://lodash.com/docs "_.findLastKey, _.forEachRight, _.forInRight, _.forOwnRight, _.partialRight") right-associative methods
+
+## Resources
+
+ * Podcasts
+  - [JavaScript Jabber](http://javascriptjabber.com/079-jsj-lo-dash-with-john-david-dalton/)
+
+ * Posts
+  - [Say âHelloâ to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
+  - [Custom builds in Lo-Dash 2.0](http://kitcambridge.be/blog/custom-builds-in-lo-dash-2-dot-0/)
+
+ * Videos
+  - [Introduction](https://vimeo.com/44154599)
+  - [Origins](https://vimeo.com/44154600)
+  - [Optimizations & builds](https://vimeo.com/44154601)
+  - [Native method use](https://vimeo.com/48576012)
+  - [Testing](https://vimeo.com/45865290)
+  - [CascadiaJS â12](http://www.youtube.com/watch?v=dpPy4f_SeEk)
+
+ A list of other community created podcasts, posts, & videos is available on our [wiki](https://github.com/lodash/lodash/wiki/Resources).
+
+## Support
+
+Tested in Chrome 5~31, Firefox 2~25, IE 6-11, Opera 9.25~17, Safari 3-7, Node.js 0.6.21~0.10.22, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5.<br>
+Automated browser test results [are available](https://saucelabs.com/u/lodash) as well as [Travis CI](https://travis-ci.org/) builds for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash).
+
+Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing.<br>
+[![Sauce Labs](http://lodash.com/_img/sauce.png)](https://saucelabs.com/ "Sauce Labs: Selenium Testing & More")
+
+## Installation & usage
+
+In browsers:
+
+```html
+<script src="lodash.js"></script>
+```
+
+Using [`npm`](http://npmjs.org/):
+
+```bash
+npm i --save lodash
+
+{sudo} npm i -g lodash
+npm ln lodash
+```
+
+In [Node.js](http://nodejs.org/) & [Ringo](http://ringojs.org/):
+
+```js
+var _ = require('lodash');
+// or as Underscore
+var _ = require('lodash/dist/lodash.underscore');
+```
+
+**Notes:**
+ * Donât assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL
+ * If Lo-Dash is installed globally, run [`npm ln lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projectâs root directory *before* requiring it
+
+In [Rhino](http://www.mozilla.org/rhino/):
+
+```js
+load('lodash.js');
+```
+
+In an AMD loader:
+
+```js
+require({
+  'packages': [
+    { 'name': 'lodash', 'location': 'path/to/lodash', 'main': 'lodash' }
+  ]
+},
+['lodash'], function(_) {
+  console.log(_.VERSION);
+});
+```
+
+## Author
+
+| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") |
+|---|
+| [John-David Dalton](http://allyoucanleet.com/) |
+
+## Contributors
+
+| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](https://twitter.com/blainebublitz "Follow @BlaineBublitz on Twitter") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
+|---|---|---|
+| [Blaine Bublitz](http://www.iceddev.com/) | [Kit Cambridge](http://kitcambridge.be/) | [Mathias Bynens](http://mathiasbynens.be/) |
+
+[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/lodash/lodash/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.compat.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.compat.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.compat.js	(revision 533)
@@ -0,0 +1,7157 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
+ * Build: `lodash -o ./dist/lodash.compat.js`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function() {
+
+  /** Used as a safe reference for `undefined` in pre ES5 environments */
+  var undefined;
+
+  /** Used to pool arrays and objects used internally */
+  var arrayPool = [],
+      objectPool = [];
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = {};
+
+  /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
+  var keyPrefix = +new Date + '';
+
+  /** Used as the size when optimizations are enabled for large arrays */
+  var largeArraySize = 75;
+
+  /** Used as the max size of the `arrayPool` and `objectPool` */
+  var maxPoolSize = 40;
+
+  /** Used to detect and test whitespace */
+  var whitespace = (
+    // whitespace
+    ' \t\x0B\f\xA0\ufeff' +
+
+    // line terminators
+    '\n\r\u2028\u2029' +
+
+    // unicode category "Zs" space separators
+    '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
+  );
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detected named functions */
+  var reFuncName = /^\s*function[ \n\r\t]+\w/;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to match leading whitespace and zeros to be removed */
+  var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to detect functions containing a `this` reference */
+  var reThis = /\bthis\b/;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to assign default `context` object properties */
+  var contextProps = [
+    'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object',
+    'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
+    'parseInt', 'setTimeout'
+  ];
+
+  /** Used to fix the JScript [[DontEnum]] bug */
+  var shadowedProps = [
+    'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+    'toLocaleString', 'toString', 'valueOf'
+  ];
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      errorClass = '[object Error]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Used to identify object classifications that `_.clone` supports */
+  var cloneableClasses = {};
+  cloneableClasses[funcClass] = false;
+  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
+  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
+  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
+
+  /** Used as an internal `_.debounce` options object */
+  var debounceOptions = {
+    'leading': false,
+    'maxWait': 0,
+    'trailing': false
+  };
+
+  /** Used as the property descriptor for `__bindData__` */
+  var descriptor = {
+    'configurable': false,
+    'enumerable': false,
+    'value': null,
+    'writable': false
+  };
+
+  /** Used as the data object for `iteratorTemplate` */
+  var iteratorData = {
+    'args': '',
+    'array': null,
+    'bottom': '',
+    'firstArg': '',
+    'init': '',
+    'keys': null,
+    'loop': '',
+    'shadowedProps': null,
+    'support': null,
+    'top': '',
+    'useHas': false
+  };
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /** Used as a reference to the global object */
+  var root = (objectTypes[typeof window] && window) || this;
+
+  /** Detect free variable `exports` */
+  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+  /** Detect the popular CommonJS extension `module.exports` */
+  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+  /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
+  var freeGlobal = objectTypes[typeof global] && global;
+  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
+    root = freeGlobal;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The base implementation of `_.indexOf` without support for binary searches
+   * or `fromIndex` constraints.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {number} [fromIndex=0] The index to search from.
+   * @returns {number} Returns the index of the matched value or `-1`.
+   */
+  function baseIndexOf(array, value, fromIndex) {
+    var index = (fromIndex || 0) - 1,
+        length = array ? array.length : 0;
+
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * An implementation of `_.contains` for cache objects that mimics the return
+   * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
+   *
+   * @private
+   * @param {Object} cache The cache object to inspect.
+   * @param {*} value The value to search for.
+   * @returns {number} Returns `0` if `value` is found, else `-1`.
+   */
+  function cacheIndexOf(cache, value) {
+    var type = typeof value;
+    cache = cache.cache;
+
+    if (type == 'boolean' || value == null) {
+      return cache[value] ? 0 : -1;
+    }
+    if (type != 'number' && type != 'string') {
+      type = 'object';
+    }
+    var key = type == 'number' ? value : keyPrefix + value;
+    cache = (cache = cache[type]) && cache[key];
+
+    return type == 'object'
+      ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
+      : (cache ? 0 : -1);
+  }
+
+  /**
+   * Adds a given value to the corresponding cache object.
+   *
+   * @private
+   * @param {*} value The value to add to the cache.
+   */
+  function cachePush(value) {
+    var cache = this.cache,
+        type = typeof value;
+
+    if (type == 'boolean' || value == null) {
+      cache[value] = true;
+    } else {
+      if (type != 'number' && type != 'string') {
+        type = 'object';
+      }
+      var key = type == 'number' ? value : keyPrefix + value,
+          typeCache = cache[type] || (cache[type] = {});
+
+      if (type == 'object') {
+        (typeCache[key] || (typeCache[key] = [])).push(value);
+      } else {
+        typeCache[key] = true;
+      }
+    }
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default callback when a given
+   * collection is a string value.
+   *
+   * @private
+   * @param {string} value The character to inspect.
+   * @returns {number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` elements, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ac = a.criteria,
+        bc = b.criteria,
+        index = -1,
+        length = ac.length;
+
+    while (++index < length) {
+      var value = ac[index],
+          other = bc[index];
+
+      if (value !== other) {
+        if (value > other || typeof value == 'undefined') {
+          return 1;
+        }
+        if (value < other || typeof other == 'undefined') {
+          return -1;
+        }
+      }
+    }
+    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+    // that causes it, under certain circumstances, to return the same value for
+    // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
+    //
+    // This also ensures a stable sort in V8 and other engines.
+    // See http://code.google.com/p/v8/issues/detail?id=90
+    return a.index - b.index;
+  }
+
+  /**
+   * Creates a cache object to optimize linear searches of large arrays.
+   *
+   * @private
+   * @param {Array} [array=[]] The array to search.
+   * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
+   */
+  function createCache(array) {
+    var index = -1,
+        length = array.length,
+        first = array[0],
+        mid = array[(length / 2) | 0],
+        last = array[length - 1];
+
+    if (first && typeof first == 'object' &&
+        mid && typeof mid == 'object' && last && typeof last == 'object') {
+      return false;
+    }
+    var cache = getObject();
+    cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
+
+    var result = getObject();
+    result.array = array;
+    result.cache = cache;
+    result.push = cachePush;
+
+    while (++index < length) {
+      result.push(array[index]);
+    }
+    return result;
+  }
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {string} match The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Gets an array from the array pool or creates a new one if the pool is empty.
+   *
+   * @private
+   * @returns {Array} The array from the pool.
+   */
+  function getArray() {
+    return arrayPool.pop() || [];
+  }
+
+  /**
+   * Gets an object from the object pool or creates a new one if the pool is empty.
+   *
+   * @private
+   * @returns {Object} The object from the pool.
+   */
+  function getObject() {
+    return objectPool.pop() || {
+      'array': null,
+      'cache': null,
+      'criteria': null,
+      'false': false,
+      'index': 0,
+      'null': false,
+      'number': null,
+      'object': null,
+      'push': null,
+      'string': null,
+      'true': false,
+      'undefined': false,
+      'value': null
+    };
+  }
+
+  /**
+   * Checks if `value` is a DOM node in IE < 9.
+   *
+   * @private
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`.
+   */
+  function isNode(value) {
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings
+    return typeof value.toString != 'function' && typeof (value + '') == 'string';
+  }
+
+  /**
+   * Releases the given array back to the array pool.
+   *
+   * @private
+   * @param {Array} [array] The array to release.
+   */
+  function releaseArray(array) {
+    array.length = 0;
+    if (arrayPool.length < maxPoolSize) {
+      arrayPool.push(array);
+    }
+  }
+
+  /**
+   * Releases the given object back to the object pool.
+   *
+   * @private
+   * @param {Object} [object] The object to release.
+   */
+  function releaseObject(object) {
+    var cache = object.cache;
+    if (cache) {
+      releaseObject(cache);
+    }
+    object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
+    if (objectPool.length < maxPoolSize) {
+      objectPool.push(object);
+    }
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used instead of `Array#slice` to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|string} collection The collection to slice.
+   * @param {number} start The start index.
+   * @param {number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Create a new `lodash` function using the given context object.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} [context=root] The context object.
+   * @returns {Function} Returns the `lodash` function.
+   */
+  function runInContext(context) {
+    // Avoid issues with some ES3 environments that attempt to use values, named
+    // after built-in constructors like `Object`, for the creation of literals.
+    // ES5 clears this up by stating that literals must use built-in constructors.
+    // See http://es5.github.io/#x11.1.5.
+    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+
+    /** Native constructor references */
+    var Array = context.Array,
+        Boolean = context.Boolean,
+        Date = context.Date,
+        Error = context.Error,
+        Function = context.Function,
+        Math = context.Math,
+        Number = context.Number,
+        Object = context.Object,
+        RegExp = context.RegExp,
+        String = context.String,
+        TypeError = context.TypeError;
+
+    /**
+     * Used for `Array` method references.
+     *
+     * Normally `Array.prototype` would suffice, however, using an array literal
+     * avoids issues in Narwhal.
+     */
+    var arrayRef = [];
+
+    /** Used for native method references */
+    var errorProto = Error.prototype,
+        objectProto = Object.prototype,
+        stringProto = String.prototype;
+
+    /** Used to restore the original `_` reference in `noConflict` */
+    var oldDash = context._;
+
+    /** Used to resolve the internal [[Class]] of values */
+    var toString = objectProto.toString;
+
+    /** Used to detect if a method is native */
+    var reNative = RegExp('^' +
+      String(toString)
+        .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+        .replace(/toString| for [^\]]+/g, '.*?') + '$'
+    );
+
+    /** Native method shortcuts */
+    var ceil = Math.ceil,
+        clearTimeout = context.clearTimeout,
+        floor = Math.floor,
+        fnToString = Function.prototype.toString,
+        getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+        hasOwnProperty = objectProto.hasOwnProperty,
+        push = arrayRef.push,
+        propertyIsEnumerable = objectProto.propertyIsEnumerable,
+        setTimeout = context.setTimeout,
+        splice = arrayRef.splice,
+        unshift = arrayRef.unshift;
+
+    /** Used to set meta data on functions */
+    var defineProperty = (function() {
+      // IE 8 only accepts DOM elements
+      try {
+        var o = {},
+            func = isNative(func = Object.defineProperty) && func,
+            result = func(o, o, o) && func;
+      } catch(e) { }
+      return result;
+    }());
+
+    /* Native method shortcuts for methods with the same name as other `lodash` methods */
+    var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
+        nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
+        nativeIsFinite = context.isFinite,
+        nativeIsNaN = context.isNaN,
+        nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
+        nativeMax = Math.max,
+        nativeMin = Math.min,
+        nativeParseInt = context.parseInt,
+        nativeRandom = Math.random;
+
+    /** Used to lookup a built-in constructor by [[Class]] */
+    var ctorByClass = {};
+    ctorByClass[arrayClass] = Array;
+    ctorByClass[boolClass] = Boolean;
+    ctorByClass[dateClass] = Date;
+    ctorByClass[funcClass] = Function;
+    ctorByClass[objectClass] = Object;
+    ctorByClass[numberClass] = Number;
+    ctorByClass[regexpClass] = RegExp;
+    ctorByClass[stringClass] = String;
+
+    /** Used to avoid iterating non-enumerable properties in IE < 9 */
+    var nonEnumProps = {};
+    nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
+    nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true };
+    nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true };
+    nonEnumProps[objectClass] = { 'constructor': true };
+
+    (function() {
+      var length = shadowedProps.length;
+      while (length--) {
+        var key = shadowedProps[length];
+        for (var className in nonEnumProps) {
+          if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) {
+            nonEnumProps[className][key] = false;
+          }
+        }
+      }
+    }());
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object which wraps the given value to enable intuitive
+     * method chaining.
+     *
+     * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+     * and `unshift`
+     *
+     * Chaining is supported in custom builds as long as the `value` method is
+     * implicitly or explicitly included in the build.
+     *
+     * The chainable wrapper functions are:
+     * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
+     * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
+     * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
+     * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
+     * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
+     * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
+     * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
+     * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
+     * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
+     * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
+     * and `zip`
+     *
+     * The non-chainable wrapper functions are:
+     * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
+     * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
+     * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
+     * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
+     * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
+     * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
+     * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
+     * `template`, `unescape`, `uniqueId`, and `value`
+     *
+     * The wrapper functions `first` and `last` return wrapped values when `n` is
+     * provided, otherwise they return unwrapped values.
+     *
+     * Explicit chaining can be enabled by using the `_.chain` method.
+     *
+     * @name _
+     * @constructor
+     * @category Chaining
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @returns {Object} Returns a `lodash` instance.
+     * @example
+     *
+     * var wrapped = _([1, 2, 3]);
+     *
+     * // returns an unwrapped value
+     * wrapped.reduce(function(sum, num) {
+     *   return sum + num;
+     * });
+     * // => 6
+     *
+     * // returns a wrapped value
+     * var squares = wrapped.map(function(num) {
+     *   return num * num;
+     * });
+     *
+     * _.isArray(squares);
+     * // => false
+     *
+     * _.isArray(squares.value());
+     * // => true
+     */
+    function lodash(value) {
+      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
+      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
+       ? value
+       : new lodashWrapper(value);
+    }
+
+    /**
+     * A fast path for creating `lodash` wrapper objects.
+     *
+     * @private
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @param {boolean} chainAll A flag to enable chaining for all methods
+     * @returns {Object} Returns a `lodash` instance.
+     */
+    function lodashWrapper(value, chainAll) {
+      this.__chain__ = !!chainAll;
+      this.__wrapped__ = value;
+    }
+    // ensure `new lodashWrapper` is an instance of `lodash`
+    lodashWrapper.prototype = lodash.prototype;
+
+    /**
+     * An object used to flag environments features.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    var support = lodash.support = {};
+
+    (function() {
+      var ctor = function() { this.x = 1; },
+          object = { '0': 1, 'length': 1 },
+          props = [];
+
+      ctor.prototype = { 'valueOf': 1, 'y': 1 };
+      for (var key in new ctor) { props.push(key); }
+      for (key in arguments) { }
+
+      /**
+       * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.argsClass = toString.call(arguments) == argsClass;
+
+      /**
+       * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.argsObject = arguments.constructor == Object && !(arguments instanceof Array);
+
+      /**
+       * Detect if `name` or `message` properties of `Error.prototype` are
+       * enumerable by default. (IE < 9, Safari < 5.1)
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name');
+
+      /**
+       * Detect if `prototype` properties are enumerable by default.
+       *
+       * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+       * (if the prototype or a property on the prototype has been set)
+       * incorrectly sets a function's `prototype` property [[Enumerable]]
+       * value to `true`.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype');
+
+      /**
+       * Detect if functions can be decompiled by `Function#toString`
+       * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
+
+      /**
+       * Detect if `Function#name` is supported (all but IE).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.funcNames = typeof Function.name == 'string';
+
+      /**
+       * Detect if `arguments` object indexes are non-enumerable
+       * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.nonEnumArgs = key != 0;
+
+      /**
+       * Detect if properties shadowing those on `Object.prototype` are non-enumerable.
+       *
+       * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+       * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.nonEnumShadows = !/valueOf/.test(props);
+
+      /**
+       * Detect if own properties are iterated after inherited properties (all but IE < 9).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.ownLast = props[0] != 'x';
+
+      /**
+       * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.
+       *
+       * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+       * and `splice()` functions that fail to remove the last element, `value[0]`,
+       * of array-like objects even though the `length` property is set to `0`.
+       * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+       * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);
+
+      /**
+       * Detect lack of support for accessing string characters by index.
+       *
+       * IE < 8 can't access characters by index and IE 8 can only access
+       * characters by index on string literals.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
+
+      /**
+       * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9)
+       * and that the JS engine errors when attempting to coerce an object to
+       * a string without a `toString` function.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      try {
+        support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
+      } catch(e) {
+        support.nodeClass = true;
+      }
+    }(1));
+
+    /**
+     * By default, the template delimiters used by Lo-Dash are similar to those in
+     * embedded Ruby (ERB). Change the following template settings to use alternative
+     * delimiters.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    lodash.templateSettings = {
+
+      /**
+       * Used to detect `data` property values to be HTML-escaped.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'escape': /<%-([\s\S]+?)%>/g,
+
+      /**
+       * Used to detect code to be evaluated.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'evaluate': /<%([\s\S]+?)%>/g,
+
+      /**
+       * Used to detect `data` property values to inject.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'interpolate': reInterpolate,
+
+      /**
+       * Used to reference the data object in the template text.
+       *
+       * @memberOf _.templateSettings
+       * @type string
+       */
+      'variable': '',
+
+      /**
+       * Used to import variables into the compiled template.
+       *
+       * @memberOf _.templateSettings
+       * @type Object
+       */
+      'imports': {
+
+        /**
+         * A reference to the `lodash` function.
+         *
+         * @memberOf _.templateSettings.imports
+         * @type Function
+         */
+        '_': lodash
+      }
+    };
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The template used to create iterator functions.
+     *
+     * @private
+     * @param {Object} data The data object used to populate the text.
+     * @returns {string} Returns the interpolated text.
+     */
+    var iteratorTemplate = function(obj) {
+
+      var __p = 'var index, iterable = ' +
+      (obj.firstArg) +
+      ', result = ' +
+      (obj.init) +
+      ';\nif (!iterable) return result;\n' +
+      (obj.top) +
+      ';';
+       if (obj.array) {
+      __p += '\nvar length = iterable.length; index = -1;\nif (' +
+      (obj.array) +
+      ') {  ';
+       if (support.unindexedChars) {
+      __p += '\n  if (isString(iterable)) {\n    iterable = iterable.split(\'\')\n  }  ';
+       }
+      __p += '\n  while (++index < length) {\n    ' +
+      (obj.loop) +
+      ';\n  }\n}\nelse {  ';
+       } else if (support.nonEnumArgs) {
+      __p += '\n  var length = iterable.length; index = -1;\n  if (length && isArguments(iterable)) {\n    while (++index < length) {\n      index += \'\';\n      ' +
+      (obj.loop) +
+      ';\n    }\n  } else {  ';
+       }
+
+       if (support.enumPrototypes) {
+      __p += '\n  var skipProto = typeof iterable == \'function\';\n  ';
+       }
+
+       if (support.enumErrorProps) {
+      __p += '\n  var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n  ';
+       }
+
+          var conditions = [];    if (support.enumPrototypes) { conditions.push('!(skipProto && index == "prototype")'); }    if (support.enumErrorProps)  { conditions.push('!(skipErrorProps && (index == "message" || index == "name"))'); }
+
+       if (obj.useHas && obj.keys) {
+      __p += '\n  var ownIndex = -1,\n      ownProps = objectTypes[typeof iterable] && keys(iterable),\n      length = ownProps ? ownProps.length : 0;\n\n  while (++ownIndex < length) {\n    index = ownProps[ownIndex];\n';
+          if (conditions.length) {
+      __p += '    if (' +
+      (conditions.join(' && ')) +
+      ') {\n  ';
+       }
+      __p +=
+      (obj.loop) +
+      ';    ';
+       if (conditions.length) {
+      __p += '\n    }';
+       }
+      __p += '\n  }  ';
+       } else {
+      __p += '\n  for (index in iterable) {\n';
+          if (obj.useHas) { conditions.push("hasOwnProperty.call(iterable, index)"); }    if (conditions.length) {
+      __p += '    if (' +
+      (conditions.join(' && ')) +
+      ') {\n  ';
+       }
+      __p +=
+      (obj.loop) +
+      ';    ';
+       if (conditions.length) {
+      __p += '\n    }';
+       }
+      __p += '\n  }    ';
+       if (support.nonEnumShadows) {
+      __p += '\n\n  if (iterable !== objectProto) {\n    var ctor = iterable.constructor,\n        isProto = iterable === (ctor && ctor.prototype),\n        className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n        nonEnum = nonEnumProps[className];\n      ';
+       for (k = 0; k < 7; k++) {
+      __p += '\n    index = \'' +
+      (obj.shadowedProps[k]) +
+      '\';\n    if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))';
+              if (!obj.useHas) {
+      __p += ' || (!nonEnum[index] && iterable[index] !== objectProto[index])';
+       }
+      __p += ') {\n      ' +
+      (obj.loop) +
+      ';\n    }      ';
+       }
+      __p += '\n  }    ';
+       }
+
+       }
+
+       if (obj.array || support.nonEnumArgs) {
+      __p += '\n}';
+       }
+      __p +=
+      (obj.bottom) +
+      ';\nreturn result';
+
+      return __p
+    };
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The base implementation of `_.bind` that creates the bound function and
+     * sets its meta data.
+     *
+     * @private
+     * @param {Array} bindData The bind data array.
+     * @returns {Function} Returns the new bound function.
+     */
+    function baseBind(bindData) {
+      var func = bindData[0],
+          partialArgs = bindData[2],
+          thisArg = bindData[4];
+
+      function bound() {
+        // `Function#bind` spec
+        // http://es5.github.io/#x15.3.4.5
+        if (partialArgs) {
+          // avoid `arguments` object deoptimizations by using `slice` instead
+          // of `Array.prototype.slice.call` and not assigning `arguments` to a
+          // variable as a ternary expression
+          var args = slice(partialArgs);
+          push.apply(args, arguments);
+        }
+        // mimic the constructor's `return` behavior
+        // http://es5.github.io/#x13.2.2
+        if (this instanceof bound) {
+          // ensure `new bound` is an instance of `func`
+          var thisBinding = baseCreate(func.prototype),
+              result = func.apply(thisBinding, args || arguments);
+          return isObject(result) ? result : thisBinding;
+        }
+        return func.apply(thisArg, args || arguments);
+      }
+      setBindData(bound, bindData);
+      return bound;
+    }
+
+    /**
+     * The base implementation of `_.clone` without argument juggling or support
+     * for `thisArg` binding.
+     *
+     * @private
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep=false] Specify a deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates clones with source counterparts.
+     * @returns {*} Returns the cloned value.
+     */
+    function baseClone(value, isDeep, callback, stackA, stackB) {
+      if (callback) {
+        var result = callback(value);
+        if (typeof result != 'undefined') {
+          return result;
+        }
+      }
+      // inspect [[Class]]
+      var isObj = isObject(value);
+      if (isObj) {
+        var className = toString.call(value);
+        if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) {
+          return value;
+        }
+        var ctor = ctorByClass[className];
+        switch (className) {
+          case boolClass:
+          case dateClass:
+            return new ctor(+value);
+
+          case numberClass:
+          case stringClass:
+            return new ctor(value);
+
+          case regexpClass:
+            result = ctor(value.source, reFlags.exec(value));
+            result.lastIndex = value.lastIndex;
+            return result;
+        }
+      } else {
+        return value;
+      }
+      var isArr = isArray(value);
+      if (isDeep) {
+        // check for circular references and return corresponding clone
+        var initedStack = !stackA;
+        stackA || (stackA = getArray());
+        stackB || (stackB = getArray());
+
+        var length = stackA.length;
+        while (length--) {
+          if (stackA[length] == value) {
+            return stackB[length];
+          }
+        }
+        result = isArr ? ctor(value.length) : {};
+      }
+      else {
+        result = isArr ? slice(value) : assign({}, value);
+      }
+      // add array properties assigned by `RegExp#exec`
+      if (isArr) {
+        if (hasOwnProperty.call(value, 'index')) {
+          result.index = value.index;
+        }
+        if (hasOwnProperty.call(value, 'input')) {
+          result.input = value.input;
+        }
+      }
+      // exit for shallow clone
+      if (!isDeep) {
+        return result;
+      }
+      // add the source value to the stack of traversed objects
+      // and associate it with its clone
+      stackA.push(value);
+      stackB.push(result);
+
+      // recursively populate clone (susceptible to call stack limits)
+      (isArr ? baseEach : forOwn)(value, function(objValue, key) {
+        result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
+      });
+
+      if (initedStack) {
+        releaseArray(stackA);
+        releaseArray(stackB);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.create` without support for assigning
+     * properties to the created object.
+     *
+     * @private
+     * @param {Object} prototype The object to inherit from.
+     * @returns {Object} Returns the new object.
+     */
+    function baseCreate(prototype, properties) {
+      return isObject(prototype) ? nativeCreate(prototype) : {};
+    }
+    // fallback for browsers without `Object.create`
+    if (!nativeCreate) {
+      baseCreate = (function() {
+        function Object() {}
+        return function(prototype) {
+          if (isObject(prototype)) {
+            Object.prototype = prototype;
+            var result = new Object;
+            Object.prototype = null;
+          }
+          return result || context.Object();
+        };
+      }());
+    }
+
+    /**
+     * The base implementation of `_.createCallback` without support for creating
+     * "_.pluck" or "_.where" style callbacks.
+     *
+     * @private
+     * @param {*} [func=identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of the created callback.
+     * @param {number} [argCount] The number of arguments the callback accepts.
+     * @returns {Function} Returns a callback function.
+     */
+    function baseCreateCallback(func, thisArg, argCount) {
+      if (typeof func != 'function') {
+        return identity;
+      }
+      // exit early for no `thisArg` or already bound by `Function#bind`
+      if (typeof thisArg == 'undefined' || !('prototype' in func)) {
+        return func;
+      }
+      var bindData = func.__bindData__;
+      if (typeof bindData == 'undefined') {
+        if (support.funcNames) {
+          bindData = !func.name;
+        }
+        bindData = bindData || !support.funcDecomp;
+        if (!bindData) {
+          var source = fnToString.call(func);
+          if (!support.funcNames) {
+            bindData = !reFuncName.test(source);
+          }
+          if (!bindData) {
+            // checks if `func` references the `this` keyword and stores the result
+            bindData = reThis.test(source);
+            setBindData(func, bindData);
+          }
+        }
+      }
+      // exit early if there are no `this` references or `func` is bound
+      if (bindData === false || (bindData !== true && bindData[1] & 1)) {
+        return func;
+      }
+      switch (argCount) {
+        case 1: return function(value) {
+          return func.call(thisArg, value);
+        };
+        case 2: return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+        case 3: return function(value, index, collection) {
+          return func.call(thisArg, value, index, collection);
+        };
+        case 4: return function(accumulator, value, index, collection) {
+          return func.call(thisArg, accumulator, value, index, collection);
+        };
+      }
+      return bind(func, thisArg);
+    }
+
+    /**
+     * The base implementation of `createWrapper` that creates the wrapper and
+     * sets its meta data.
+     *
+     * @private
+     * @param {Array} bindData The bind data array.
+     * @returns {Function} Returns the new function.
+     */
+    function baseCreateWrapper(bindData) {
+      var func = bindData[0],
+          bitmask = bindData[1],
+          partialArgs = bindData[2],
+          partialRightArgs = bindData[3],
+          thisArg = bindData[4],
+          arity = bindData[5];
+
+      var isBind = bitmask & 1,
+          isBindKey = bitmask & 2,
+          isCurry = bitmask & 4,
+          isCurryBound = bitmask & 8,
+          key = func;
+
+      function bound() {
+        var thisBinding = isBind ? thisArg : this;
+        if (partialArgs) {
+          var args = slice(partialArgs);
+          push.apply(args, arguments);
+        }
+        if (partialRightArgs || isCurry) {
+          args || (args = slice(arguments));
+          if (partialRightArgs) {
+            push.apply(args, partialRightArgs);
+          }
+          if (isCurry && args.length < arity) {
+            bitmask |= 16 & ~32;
+            return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
+          }
+        }
+        args || (args = arguments);
+        if (isBindKey) {
+          func = thisBinding[key];
+        }
+        if (this instanceof bound) {
+          thisBinding = baseCreate(func.prototype);
+          var result = func.apply(thisBinding, args);
+          return isObject(result) ? result : thisBinding;
+        }
+        return func.apply(thisBinding, args);
+      }
+      setBindData(bound, bindData);
+      return bound;
+    }
+
+    /**
+     * The base implementation of `_.difference` that accepts a single array
+     * of values to exclude.
+     *
+     * @private
+     * @param {Array} array The array to process.
+     * @param {Array} [values] The array of values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     */
+    function baseDifference(array, values) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array ? array.length : 0,
+          isLarge = length >= largeArraySize && indexOf === baseIndexOf,
+          result = [];
+
+      if (isLarge) {
+        var cache = createCache(values);
+        if (cache) {
+          indexOf = cacheIndexOf;
+          values = cache;
+        } else {
+          isLarge = false;
+        }
+      }
+      while (++index < length) {
+        var value = array[index];
+        if (indexOf(values, value) < 0) {
+          result.push(value);
+        }
+      }
+      if (isLarge) {
+        releaseObject(values);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.flatten` without support for callback
+     * shorthands or `thisArg` binding.
+     *
+     * @private
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+     * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
+     * @param {number} [fromIndex=0] The index to start from.
+     * @returns {Array} Returns a new flattened array.
+     */
+    function baseFlatten(array, isShallow, isStrict, fromIndex) {
+      var index = (fromIndex || 0) - 1,
+          length = array ? array.length : 0,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+
+        if (value && typeof value == 'object' && typeof value.length == 'number'
+            && (isArray(value) || isArguments(value))) {
+          // recursively flatten arrays (susceptible to call stack limits)
+          if (!isShallow) {
+            value = baseFlatten(value, isShallow, isStrict);
+          }
+          var valIndex = -1,
+              valLength = value.length,
+              resIndex = result.length;
+
+          result.length += valLength;
+          while (++valIndex < valLength) {
+            result[resIndex++] = value[valIndex];
+          }
+        } else if (!isStrict) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.isEqual`, without support for `thisArg` binding,
+     * that allows partial "_.where" style comparisons.
+     *
+     * @private
+     * @param {*} a The value to compare.
+     * @param {*} b The other value to compare.
+     * @param {Function} [callback] The function to customize comparing values.
+     * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
+     * @param {Array} [stackA=[]] Tracks traversed `a` objects.
+     * @param {Array} [stackB=[]] Tracks traversed `b` objects.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     */
+    function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
+      // used to indicate that when comparing objects, `a` has at least the properties of `b`
+      if (callback) {
+        var result = callback(a, b);
+        if (typeof result != 'undefined') {
+          return !!result;
+        }
+      }
+      // exit early for identical values
+      if (a === b) {
+        // treat `+0` vs. `-0` as not equal
+        return a !== 0 || (1 / a == 1 / b);
+      }
+      var type = typeof a,
+          otherType = typeof b;
+
+      // exit early for unlike primitive values
+      if (a === a &&
+          !(a && objectTypes[type]) &&
+          !(b && objectTypes[otherType])) {
+        return false;
+      }
+      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
+      // http://es5.github.io/#x15.3.4.4
+      if (a == null || b == null) {
+        return a === b;
+      }
+      // compare [[Class]] names
+      var className = toString.call(a),
+          otherClass = toString.call(b);
+
+      if (className == argsClass) {
+        className = objectClass;
+      }
+      if (otherClass == argsClass) {
+        otherClass = objectClass;
+      }
+      if (className != otherClass) {
+        return false;
+      }
+      switch (className) {
+        case boolClass:
+        case dateClass:
+          // coerce dates and booleans to numbers, dates to milliseconds and booleans
+          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
+          return +a == +b;
+
+        case numberClass:
+          // treat `NaN` vs. `NaN` as equal
+          return (a != +a)
+            ? b != +b
+            // but treat `+0` vs. `-0` as not equal
+            : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+        case regexpClass:
+        case stringClass:
+          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
+          // treat string primitives and their corresponding object instances as equal
+          return a == String(b);
+      }
+      var isArr = className == arrayClass;
+      if (!isArr) {
+        // unwrap any `lodash` wrapped values
+        var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
+            bWrapped = hasOwnProperty.call(b, '__wrapped__');
+
+        if (aWrapped || bWrapped) {
+          return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
+        }
+        // exit for functions and DOM nodes
+        if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {
+          return false;
+        }
+        // in older versions of Opera, `arguments` objects have `Array` constructors
+        var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,
+            ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
+
+        // non `Object` object instances with different constructors are not equal
+        if (ctorA != ctorB &&
+              !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
+              ('constructor' in a && 'constructor' in b)
+            ) {
+          return false;
+        }
+      }
+      // assume cyclic structures are equal
+      // the algorithm for detecting cyclic structures is adapted from ES 5.1
+      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
+      var initedStack = !stackA;
+      stackA || (stackA = getArray());
+      stackB || (stackB = getArray());
+
+      var length = stackA.length;
+      while (length--) {
+        if (stackA[length] == a) {
+          return stackB[length] == b;
+        }
+      }
+      var size = 0;
+      result = true;
+
+      // add `a` and `b` to the stack of traversed objects
+      stackA.push(a);
+      stackB.push(b);
+
+      // recursively compare objects and arrays (susceptible to call stack limits)
+      if (isArr) {
+        // compare lengths to determine if a deep comparison is necessary
+        length = a.length;
+        size = b.length;
+        result = size == length;
+
+        if (result || isWhere) {
+          // deep compare the contents, ignoring non-numeric properties
+          while (size--) {
+            var index = length,
+                value = b[size];
+
+            if (isWhere) {
+              while (index--) {
+                if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
+                  break;
+                }
+              }
+            } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
+              break;
+            }
+          }
+        }
+      }
+      else {
+        // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
+        // which, in this case, is more costly
+        forIn(b, function(value, key, b) {
+          if (hasOwnProperty.call(b, key)) {
+            // count the number of properties.
+            size++;
+            // deep compare each property value.
+            return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
+          }
+        });
+
+        if (result && !isWhere) {
+          // ensure both objects have the same number of properties
+          forIn(a, function(value, key, a) {
+            if (hasOwnProperty.call(a, key)) {
+              // `size` will be `-1` if `a` has more properties than `b`
+              return (result = --size > -1);
+            }
+          });
+        }
+      }
+      stackA.pop();
+      stackB.pop();
+
+      if (initedStack) {
+        releaseArray(stackA);
+        releaseArray(stackB);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.merge` without argument juggling or support
+     * for `thisArg` binding.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @param {Function} [callback] The function to customize merging properties.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates values with source counterparts.
+     */
+    function baseMerge(object, source, callback, stackA, stackB) {
+      (isArray(source) ? forEach : forOwn)(source, function(source, key) {
+        var found,
+            isArr,
+            result = source,
+            value = object[key];
+
+        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+          // avoid merging previously merged cyclic sources
+          var stackLength = stackA.length;
+          while (stackLength--) {
+            if ((found = stackA[stackLength] == source)) {
+              value = stackB[stackLength];
+              break;
+            }
+          }
+          if (!found) {
+            var isShallow;
+            if (callback) {
+              result = callback(value, source);
+              if ((isShallow = typeof result != 'undefined')) {
+                value = result;
+              }
+            }
+            if (!isShallow) {
+              value = isArr
+                ? (isArray(value) ? value : [])
+                : (isPlainObject(value) ? value : {});
+            }
+            // add `source` and associated `value` to the stack of traversed objects
+            stackA.push(source);
+            stackB.push(value);
+
+            // recursively merge objects and arrays (susceptible to call stack limits)
+            if (!isShallow) {
+              baseMerge(value, source, callback, stackA, stackB);
+            }
+          }
+        }
+        else {
+          if (callback) {
+            result = callback(value, source);
+            if (typeof result == 'undefined') {
+              result = source;
+            }
+          }
+          if (typeof result != 'undefined') {
+            value = result;
+          }
+        }
+        object[key] = value;
+      });
+    }
+
+    /**
+     * The base implementation of `_.random` without argument juggling or support
+     * for returning floating-point numbers.
+     *
+     * @private
+     * @param {number} min The minimum possible value.
+     * @param {number} max The maximum possible value.
+     * @returns {number} Returns a random number.
+     */
+    function baseRandom(min, max) {
+      return min + floor(nativeRandom() * (max - min + 1));
+    }
+
+    /**
+     * The base implementation of `_.uniq` without support for callback shorthands
+     * or `thisArg` binding.
+     *
+     * @private
+     * @param {Array} array The array to process.
+     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+     * @param {Function} [callback] The function called per iteration.
+     * @returns {Array} Returns a duplicate-value-free array.
+     */
+    function baseUniq(array, isSorted, callback) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array ? array.length : 0,
+          result = [];
+
+      var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
+          seen = (callback || isLarge) ? getArray() : result;
+
+      if (isLarge) {
+        var cache = createCache(seen);
+        indexOf = cacheIndexOf;
+        seen = cache;
+      }
+      while (++index < length) {
+        var value = array[index],
+            computed = callback ? callback(value, index, array) : value;
+
+        if (isSorted
+              ? !index || seen[seen.length - 1] !== computed
+              : indexOf(seen, computed) < 0
+            ) {
+          if (callback || isLarge) {
+            seen.push(computed);
+          }
+          result.push(value);
+        }
+      }
+      if (isLarge) {
+        releaseArray(seen.array);
+        releaseObject(seen);
+      } else if (callback) {
+        releaseArray(seen);
+      }
+      return result;
+    }
+
+    /**
+     * Creates a function that aggregates a collection, creating an object composed
+     * of keys generated from the results of running each element of the collection
+     * through a callback. The given `setter` function sets the keys and values
+     * of the composed object.
+     *
+     * @private
+     * @param {Function} setter The setter function.
+     * @returns {Function} Returns the new aggregator function.
+     */
+    function createAggregator(setter) {
+      return function(collection, callback, thisArg) {
+        var result = {};
+        callback = lodash.createCallback(callback, thisArg, 3);
+
+        if (isArray(collection)) {
+          var index = -1,
+              length = collection.length;
+
+          while (++index < length) {
+            var value = collection[index];
+            setter(result, value, callback(value, index, collection), collection);
+          }
+        } else {
+          baseEach(collection, function(value, key, collection) {
+            setter(result, value, callback(value, key, collection), collection);
+          });
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that, when called, either curries or invokes `func`
+     * with an optional `this` binding and partially applied arguments.
+     *
+     * @private
+     * @param {Function|string} func The function or method name to reference.
+     * @param {number} bitmask The bitmask of method flags to compose.
+     *  The bitmask may be composed of the following flags:
+     *  1 - `_.bind`
+     *  2 - `_.bindKey`
+     *  4 - `_.curry`
+     *  8 - `_.curry` (bound)
+     *  16 - `_.partial`
+     *  32 - `_.partialRight`
+     * @param {Array} [partialArgs] An array of arguments to prepend to those
+     *  provided to the new function.
+     * @param {Array} [partialRightArgs] An array of arguments to append to those
+     *  provided to the new function.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {number} [arity] The arity of `func`.
+     * @returns {Function} Returns the new function.
+     */
+    function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
+      var isBind = bitmask & 1,
+          isBindKey = bitmask & 2,
+          isCurry = bitmask & 4,
+          isCurryBound = bitmask & 8,
+          isPartial = bitmask & 16,
+          isPartialRight = bitmask & 32;
+
+      if (!isBindKey && !isFunction(func)) {
+        throw new TypeError;
+      }
+      if (isPartial && !partialArgs.length) {
+        bitmask &= ~16;
+        isPartial = partialArgs = false;
+      }
+      if (isPartialRight && !partialRightArgs.length) {
+        bitmask &= ~32;
+        isPartialRight = partialRightArgs = false;
+      }
+      var bindData = func && func.__bindData__;
+      if (bindData && bindData !== true) {
+        // clone `bindData`
+        bindData = slice(bindData);
+        if (bindData[2]) {
+          bindData[2] = slice(bindData[2]);
+        }
+        if (bindData[3]) {
+          bindData[3] = slice(bindData[3]);
+        }
+        // set `thisBinding` is not previously bound
+        if (isBind && !(bindData[1] & 1)) {
+          bindData[4] = thisArg;
+        }
+        // set if previously bound but not currently (subsequent curried functions)
+        if (!isBind && bindData[1] & 1) {
+          bitmask |= 8;
+        }
+        // set curried arity if not yet set
+        if (isCurry && !(bindData[1] & 4)) {
+          bindData[5] = arity;
+        }
+        // append partial left arguments
+        if (isPartial) {
+          push.apply(bindData[2] || (bindData[2] = []), partialArgs);
+        }
+        // append partial right arguments
+        if (isPartialRight) {
+          unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
+        }
+        // merge flags
+        bindData[1] |= bitmask;
+        return createWrapper.apply(null, bindData);
+      }
+      // fast path for `_.bind`
+      var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
+      return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
+    }
+
+    /**
+     * Creates compiled iteration functions.
+     *
+     * @private
+     * @param {...Object} [options] The compile options object(s).
+     * @param {string} [options.array] Code to determine if the iterable is an array or array-like.
+     * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop.
+     * @param {Function} [options.keys] A reference to `_.keys` for use in own property iteration.
+     * @param {string} [options.args] A comma separated string of iteration function arguments.
+     * @param {string} [options.top] Code to execute before the iteration branches.
+     * @param {string} [options.loop] Code to execute in the object loop.
+     * @param {string} [options.bottom] Code to execute after the iteration branches.
+     * @returns {Function} Returns the compiled function.
+     */
+    function createIterator() {
+      // data properties
+      iteratorData.shadowedProps = shadowedProps;
+
+      // iterator options
+      iteratorData.array = iteratorData.bottom = iteratorData.loop = iteratorData.top = '';
+      iteratorData.init = 'iterable';
+      iteratorData.useHas = true;
+
+      // merge options into a template data object
+      for (var object, index = 0; object = arguments[index]; index++) {
+        for (var key in object) {
+          iteratorData[key] = object[key];
+        }
+      }
+      var args = iteratorData.args;
+      iteratorData.firstArg = /^[^,]+/.exec(args)[0];
+
+      // create the function factory
+      var factory = Function(
+          'baseCreateCallback, errorClass, errorProto, hasOwnProperty, ' +
+          'indicatorObject, isArguments, isArray, isString, keys, objectProto, ' +
+          'objectTypes, nonEnumProps, stringClass, stringProto, toString',
+        'return function(' + args + ') {\n' + iteratorTemplate(iteratorData) + '\n}'
+      );
+
+      // return the compiled function
+      return factory(
+        baseCreateCallback, errorClass, errorProto, hasOwnProperty,
+        indicatorObject, isArguments, isArray, isString, iteratorData.keys, objectProto,
+        objectTypes, nonEnumProps, stringClass, stringProto, toString
+      );
+    }
+
+    /**
+     * Used by `escape` to convert characters to HTML entities.
+     *
+     * @private
+     * @param {string} match The matched character to escape.
+     * @returns {string} Returns the escaped character.
+     */
+    function escapeHtmlChar(match) {
+      return htmlEscapes[match];
+    }
+
+    /**
+     * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+     * customized, this method returns the custom method, otherwise it returns
+     * the `baseIndexOf` function.
+     *
+     * @private
+     * @returns {Function} Returns the "indexOf" function.
+     */
+    function getIndexOf() {
+      var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
+      return result;
+    }
+
+    /**
+     * Checks if `value` is a native function.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
+     */
+    function isNative(value) {
+      return typeof value == 'function' && reNative.test(value);
+    }
+
+    /**
+     * Sets `this` binding data on a given function.
+     *
+     * @private
+     * @param {Function} func The function to set data on.
+     * @param {Array} value The data array to set.
+     */
+    var setBindData = !defineProperty ? noop : function(func, value) {
+      descriptor.value = value;
+      defineProperty(func, '__bindData__', descriptor);
+    };
+
+    /**
+     * A fallback implementation of `isPlainObject` which checks if a given value
+     * is an object created by the `Object` constructor, assuming objects created
+     * by the `Object` constructor have no inherited enumerable properties and that
+     * there are no `Object.prototype` extensions.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     */
+    function shimIsPlainObject(value) {
+      var ctor,
+          result;
+
+      // avoid non Object objects, `arguments` objects, and DOM elements
+      if (!(value && toString.call(value) == objectClass) ||
+          (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor)) ||
+          (!support.argsClass && isArguments(value)) ||
+          (!support.nodeClass && isNode(value))) {
+        return false;
+      }
+      // IE < 9 iterates inherited properties before own properties. If the first
+      // iterated property is an object's own property then there are no inherited
+      // enumerable properties.
+      if (support.ownLast) {
+        forIn(value, function(value, key, object) {
+          result = hasOwnProperty.call(object, key);
+          return false;
+        });
+        return result !== false;
+      }
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return typeof result == 'undefined' || hasOwnProperty.call(value, result);
+    }
+
+    /**
+     * Used by `unescape` to convert HTML entities to characters.
+     *
+     * @private
+     * @param {string} match The matched character to unescape.
+     * @returns {string} Returns the unescaped character.
+     */
+    function unescapeHtmlChar(match) {
+      return htmlUnescapes[match];
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Checks if `value` is an `arguments` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+     * @example
+     *
+     * (function() { return _.isArguments(arguments); })(1, 2, 3);
+     * // => true
+     *
+     * _.isArguments([1, 2, 3]);
+     * // => false
+     */
+    function isArguments(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        toString.call(value) == argsClass || false;
+    }
+    // fallback for browsers that can't detect `arguments` objects by [[Class]]
+    if (!support.argsClass) {
+      isArguments = function(value) {
+        return value && typeof value == 'object' && typeof value.length == 'number' &&
+          hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false;
+      };
+    }
+
+    /**
+     * Checks if `value` is an array.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
+     * @example
+     *
+     * (function() { return _.isArray(arguments); })();
+     * // => false
+     *
+     * _.isArray([1, 2, 3]);
+     * // => true
+     */
+    var isArray = nativeIsArray || function(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        toString.call(value) == arrayClass || false;
+    };
+
+    /**
+     * A fallback implementation of `Object.keys` which produces an array of the
+     * given object's own enumerable property names.
+     *
+     * @private
+     * @type Function
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names.
+     */
+    var shimKeys = createIterator({
+      'args': 'object',
+      'init': '[]',
+      'top': 'if (!(objectTypes[typeof object])) return result',
+      'loop': 'result.push(index)'
+    });
+
+    /**
+     * Creates an array composed of the own enumerable property names of an object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names.
+     * @example
+     *
+     * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
+     */
+    var keys = !nativeKeys ? shimKeys : function(object) {
+      if (!isObject(object)) {
+        return [];
+      }
+      if ((support.enumPrototypes && typeof object == 'function') ||
+          (support.nonEnumArgs && object.length && isArguments(object))) {
+        return shimKeys(object);
+      }
+      return nativeKeys(object);
+    };
+
+    /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
+    var eachIteratorOptions = {
+      'args': 'collection, callback, thisArg',
+      'top': "callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",
+      'array': "typeof length == 'number'",
+      'keys': keys,
+      'loop': 'if (callback(iterable[index], index, collection) === false) return result'
+    };
+
+    /** Reusable iterator options for `assign` and `defaults` */
+    var defaultsIteratorOptions = {
+      'args': 'object, source, guard',
+      'top':
+        'var args = arguments,\n' +
+        '    argsIndex = 0,\n' +
+        "    argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
+        'while (++argsIndex < argsLength) {\n' +
+        '  iterable = args[argsIndex];\n' +
+        '  if (iterable && objectTypes[typeof iterable]) {',
+      'keys': keys,
+      'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
+      'bottom': '  }\n}'
+    };
+
+    /** Reusable iterator options for `forIn` and `forOwn` */
+    var forOwnIteratorOptions = {
+      'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
+      'array': false
+    };
+
+    /**
+     * Used to convert characters to HTML entities:
+     *
+     * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+     * don't require escaping in HTML and have no special meaning unless they're part
+     * of a tag or an unquoted attribute value.
+     * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+     */
+    var htmlEscapes = {
+      '&': '&amp;',
+      '<': '&lt;',
+      '>': '&gt;',
+      '"': '&quot;',
+      "'": '&#39;'
+    };
+
+    /** Used to convert HTML entities to characters */
+    var htmlUnescapes = invert(htmlEscapes);
+
+    /** Used to match HTML entities and HTML characters */
+    var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
+        reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
+
+    /**
+     * A function compiled to iterate `arguments` objects, arrays, objects, and
+     * strings consistenly across environments, executing the callback for each
+     * element in the collection. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index|key, collection). Callbacks may exit
+     * iteration early by explicitly returning `false`.
+     *
+     * @private
+     * @type Function
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     */
+    var baseEach = createIterator(eachIteratorOptions);
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object. Subsequent sources will overwrite property assignments of previous
+     * sources. If a callback is provided it will be executed to produce the
+     * assigned values. The callback is bound to `thisArg` and invoked with two
+     * arguments; (objectValue, sourceValue).
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @alias extend
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param {Function} [callback] The function to customize assigning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
+     * // => { 'name': 'fred', 'employer': 'slate' }
+     *
+     * var defaults = _.partialRight(_.assign, function(a, b) {
+     *   return typeof a == 'undefined' ? b : a;
+     * });
+     *
+     * var object = { 'name': 'barney' };
+     * defaults(object, { 'name': 'fred', 'employer': 'slate' });
+     * // => { 'name': 'barney', 'employer': 'slate' }
+     */
+    var assign = createIterator(defaultsIteratorOptions, {
+      'top':
+        defaultsIteratorOptions.top.replace(';',
+          ';\n' +
+          "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
+          '  var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
+          "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
+          '  callback = args[--argsLength];\n' +
+          '}'
+        ),
+      'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
+    });
+
+    /**
+     * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
+     * be cloned, otherwise they will be assigned by reference. If a callback
+     * is provided it will be executed to produce the cloned values. If the
+     * callback returns `undefined` cloning will be handled by the method instead.
+     * The callback is bound to `thisArg` and invoked with one argument; (value).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep=false] Specify a deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the cloned value.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * var shallow = _.clone(characters);
+     * shallow[0] === characters[0];
+     * // => true
+     *
+     * var deep = _.clone(characters, true);
+     * deep[0] === characters[0];
+     * // => false
+     *
+     * _.mixin({
+     *   'clone': _.partialRight(_.clone, function(value) {
+     *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+     *   })
+     * });
+     *
+     * var clone = _.clone(document.body);
+     * clone.childNodes.length;
+     * // => 0
+     */
+    function clone(value, isDeep, callback, thisArg) {
+      // allows working with "Collections" methods without using their `index`
+      // and `collection` arguments for `isDeep` and `callback`
+      if (typeof isDeep != 'boolean' && isDeep != null) {
+        thisArg = callback;
+        callback = isDeep;
+        isDeep = false;
+      }
+      return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+    }
+
+    /**
+     * Creates a deep clone of `value`. If a callback is provided it will be
+     * executed to produce the cloned values. If the callback returns `undefined`
+     * cloning will be handled by the method instead. The callback is bound to
+     * `thisArg` and invoked with one argument; (value).
+     *
+     * Note: This method is loosely based on the structured clone algorithm. Functions
+     * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+     * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+     * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the deep cloned value.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * var deep = _.cloneDeep(characters);
+     * deep[0] === characters[0];
+     * // => false
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'node': element
+     * };
+     *
+     * var clone = _.cloneDeep(view, function(value) {
+     *   return _.isElement(value) ? value.cloneNode(true) : undefined;
+     * });
+     *
+     * clone.node == view.node;
+     * // => false
+     */
+    function cloneDeep(value, callback, thisArg) {
+      return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+    }
+
+    /**
+     * Creates an object that inherits from the given `prototype` object. If a
+     * `properties` object is provided its own enumerable properties are assigned
+     * to the created object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} prototype The object to inherit from.
+     * @param {Object} [properties] The properties to assign to the object.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * function Circle() {
+     *   Shape.call(this);
+     * }
+     *
+     * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
+     *
+     * var circle = new Circle;
+     * circle instanceof Circle;
+     * // => true
+     *
+     * circle instanceof Shape;
+     * // => true
+     */
+    function create(prototype, properties) {
+      var result = baseCreate(prototype);
+      return properties ? assign(result, properties) : result;
+    }
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object for all destination properties that resolve to `undefined`. Once a
+     * property is set, additional defaults of the same property will be ignored.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param- {Object} [guard] Allows working with `_.reduce` without using its
+     *  `key` and `object` arguments as sources.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * var object = { 'name': 'barney' };
+     * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
+     * // => { 'name': 'barney', 'employer': 'slate' }
+     */
+    var defaults = createIterator(defaultsIteratorOptions);
+
+    /**
+     * This method is like `_.findIndex` except that it returns the key of the
+     * first element that passes the callback check, instead of the element itself.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [callback=identity] The function called per
+     *  iteration. If a property name or object is provided it will be used to
+     *  create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
+     * @example
+     *
+     * var characters = {
+     *   'barney': {  'age': 36, 'blocked': false },
+     *   'fred': {    'age': 40, 'blocked': true },
+     *   'pebbles': { 'age': 1,  'blocked': false }
+     * };
+     *
+     * _.findKey(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => 'barney' (property order is not guaranteed across environments)
+     *
+     * // using "_.where" callback shorthand
+     * _.findKey(characters, { 'age': 1 });
+     * // => 'pebbles'
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findKey(characters, 'blocked');
+     * // => 'fred'
+     */
+    function findKey(object, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forOwn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result = key;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * This method is like `_.findKey` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [callback=identity] The function called per
+     *  iteration. If a property name or object is provided it will be used to
+     *  create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
+     * @example
+     *
+     * var characters = {
+     *   'barney': {  'age': 36, 'blocked': true },
+     *   'fred': {    'age': 40, 'blocked': false },
+     *   'pebbles': { 'age': 1,  'blocked': true }
+     * };
+     *
+     * _.findLastKey(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => returns `pebbles`, assuming `_.findKey` returns `barney`
+     *
+     * // using "_.where" callback shorthand
+     * _.findLastKey(characters, { 'age': 40 });
+     * // => 'fred'
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findLastKey(characters, 'blocked');
+     * // => 'pebbles'
+     */
+    function findLastKey(object, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forOwnRight(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result = key;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Iterates over own and inherited enumerable properties of an object,
+     * executing the callback for each property. The callback is bound to `thisArg`
+     * and invoked with three arguments; (value, key, object). Callbacks may exit
+     * iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * Shape.prototype.move = function(x, y) {
+     *   this.x += x;
+     *   this.y += y;
+     * };
+     *
+     * _.forIn(new Shape, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
+     */
+    var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
+      'useHas': false
+    });
+
+    /**
+     * This method is like `_.forIn` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * Shape.prototype.move = function(x, y) {
+     *   this.x += x;
+     *   this.y += y;
+     * };
+     *
+     * _.forInRight(new Shape, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
+     */
+    function forInRight(object, callback, thisArg) {
+      var pairs = [];
+
+      forIn(object, function(value, key) {
+        pairs.push(key, value);
+      });
+
+      var length = pairs.length;
+      callback = baseCreateCallback(callback, thisArg, 3);
+      while (length--) {
+        if (callback(pairs[length--], pairs[length], object) === false) {
+          break;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Iterates over own enumerable properties of an object, executing the callback
+     * for each property. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, key, object). Callbacks may exit iteration early by
+     * explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+     *   console.log(key);
+     * });
+     * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
+     */
+    var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
+
+    /**
+     * This method is like `_.forOwn` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
+     */
+    function forOwnRight(object, callback, thisArg) {
+      var props = keys(object),
+          length = props.length;
+
+      callback = baseCreateCallback(callback, thisArg, 3);
+      while (length--) {
+        var key = props[length];
+        if (callback(object[key], key, object) === false) {
+          break;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Creates a sorted array of property names of all enumerable properties,
+     * own and inherited, of `object` that have function values.
+     *
+     * @static
+     * @memberOf _
+     * @alias methods
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names that have function values.
+     * @example
+     *
+     * _.functions(_);
+     * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+     */
+    function functions(object) {
+      var result = [];
+      forIn(object, function(value, key) {
+        if (isFunction(value)) {
+          result.push(key);
+        }
+      });
+      return result.sort();
+    }
+
+    /**
+     * Checks if the specified property name exists as a direct property of `object`,
+     * instead of an inherited property.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @param {string} key The name of the property to check.
+     * @returns {boolean} Returns `true` if key is a direct property, else `false`.
+     * @example
+     *
+     * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+     * // => true
+     */
+    function has(object, key) {
+      return object ? hasOwnProperty.call(object, key) : false;
+    }
+
+    /**
+     * Creates an object composed of the inverted keys and values of the given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to invert.
+     * @returns {Object} Returns the created inverted object.
+     * @example
+     *
+     * _.invert({ 'first': 'fred', 'second': 'barney' });
+     * // => { 'fred': 'first', 'barney': 'second' }
+     */
+    function invert(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = {};
+
+      while (++index < length) {
+        var key = props[index];
+        result[object[key]] = key;
+      }
+      return result;
+    }
+
+    /**
+     * Checks if `value` is a boolean value.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
+     * @example
+     *
+     * _.isBoolean(null);
+     * // => false
+     */
+    function isBoolean(value) {
+      return value === true || value === false ||
+        value && typeof value == 'object' && toString.call(value) == boolClass || false;
+    }
+
+    /**
+     * Checks if `value` is a date.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
+     * @example
+     *
+     * _.isDate(new Date);
+     * // => true
+     */
+    function isDate(value) {
+      return value && typeof value == 'object' && toString.call(value) == dateClass || false;
+    }
+
+    /**
+     * Checks if `value` is a DOM element.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
+     * @example
+     *
+     * _.isElement(document.body);
+     * // => true
+     */
+    function isElement(value) {
+      return value && value.nodeType === 1 || false;
+    }
+
+    /**
+     * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+     * length of `0` and objects with no own enumerable properties are considered
+     * "empty".
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Array|Object|string} value The value to inspect.
+     * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
+     * @example
+     *
+     * _.isEmpty([1, 2, 3]);
+     * // => false
+     *
+     * _.isEmpty({});
+     * // => true
+     *
+     * _.isEmpty('');
+     * // => true
+     */
+    function isEmpty(value) {
+      var result = true;
+      if (!value) {
+        return result;
+      }
+      var className = toString.call(value),
+          length = value.length;
+
+      if ((className == arrayClass || className == stringClass ||
+          (support.argsClass ? className == argsClass : isArguments(value))) ||
+          (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+        return !length;
+      }
+      forOwn(value, function() {
+        return (result = false);
+      });
+      return result;
+    }
+
+    /**
+     * Performs a deep comparison between two values to determine if they are
+     * equivalent to each other. If a callback is provided it will be executed
+     * to compare values. If the callback returns `undefined` comparisons will
+     * be handled by the method instead. The callback is bound to `thisArg` and
+     * invoked with two arguments; (a, b).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} a The value to compare.
+     * @param {*} b The other value to compare.
+     * @param {Function} [callback] The function to customize comparing values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * var copy = { 'name': 'fred' };
+     *
+     * object == copy;
+     * // => false
+     *
+     * _.isEqual(object, copy);
+     * // => true
+     *
+     * var words = ['hello', 'goodbye'];
+     * var otherWords = ['hi', 'goodbye'];
+     *
+     * _.isEqual(words, otherWords, function(a, b) {
+     *   var reGreet = /^(?:hello|hi)$/i,
+     *       aGreet = _.isString(a) && reGreet.test(a),
+     *       bGreet = _.isString(b) && reGreet.test(b);
+     *
+     *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+     * });
+     * // => true
+     */
+    function isEqual(a, b, callback, thisArg) {
+      return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
+    }
+
+    /**
+     * Checks if `value` is, or can be coerced to, a finite number.
+     *
+     * Note: This is not the same as native `isFinite` which will return true for
+     * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
+     * @example
+     *
+     * _.isFinite(-101);
+     * // => true
+     *
+     * _.isFinite('10');
+     * // => true
+     *
+     * _.isFinite(true);
+     * // => false
+     *
+     * _.isFinite('');
+     * // => false
+     *
+     * _.isFinite(Infinity);
+     * // => false
+     */
+    function isFinite(value) {
+      return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+    }
+
+    /**
+     * Checks if `value` is a function.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
+     * @example
+     *
+     * _.isFunction(_);
+     * // => true
+     */
+    function isFunction(value) {
+      return typeof value == 'function';
+    }
+    // fallback for older versions of Chrome and Safari
+    if (isFunction(/x/)) {
+      isFunction = function(value) {
+        return typeof value == 'function' && toString.call(value) == funcClass;
+      };
+    }
+
+    /**
+     * Checks if `value` is the language type of Object.
+     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
+     * @example
+     *
+     * _.isObject({});
+     * // => true
+     *
+     * _.isObject([1, 2, 3]);
+     * // => true
+     *
+     * _.isObject(1);
+     * // => false
+     */
+    function isObject(value) {
+      // check if the value is the ECMAScript language type of Object
+      // http://es5.github.io/#x8
+      // and avoid a V8 bug
+      // http://code.google.com/p/v8/issues/detail?id=2291
+      return !!(value && objectTypes[typeof value]);
+    }
+
+    /**
+     * Checks if `value` is `NaN`.
+     *
+     * Note: This is not the same as native `isNaN` which will return `true` for
+     * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
+     * @example
+     *
+     * _.isNaN(NaN);
+     * // => true
+     *
+     * _.isNaN(new Number(NaN));
+     * // => true
+     *
+     * isNaN(undefined);
+     * // => true
+     *
+     * _.isNaN(undefined);
+     * // => false
+     */
+    function isNaN(value) {
+      // `NaN` as a primitive is the only value that is not equal to itself
+      // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+      return isNumber(value) && value != +value;
+    }
+
+    /**
+     * Checks if `value` is `null`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
+     * @example
+     *
+     * _.isNull(null);
+     * // => true
+     *
+     * _.isNull(undefined);
+     * // => false
+     */
+    function isNull(value) {
+      return value === null;
+    }
+
+    /**
+     * Checks if `value` is a number.
+     *
+     * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
+     * @example
+     *
+     * _.isNumber(8.4 * 5);
+     * // => true
+     */
+    function isNumber(value) {
+      return typeof value == 'number' ||
+        value && typeof value == 'object' && toString.call(value) == numberClass || false;
+    }
+
+    /**
+     * Checks if `value` is an object created by the `Object` constructor.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * _.isPlainObject(new Shape);
+     * // => false
+     *
+     * _.isPlainObject([1, 2, 3]);
+     * // => false
+     *
+     * _.isPlainObject({ 'x': 0, 'y': 0 });
+     * // => true
+     */
+    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+      if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) {
+        return false;
+      }
+      var valueOf = value.valueOf,
+          objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+      return objProto
+        ? (value == objProto || getPrototypeOf(value) == objProto)
+        : shimIsPlainObject(value);
+    };
+
+    /**
+     * Checks if `value` is a regular expression.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
+     * @example
+     *
+     * _.isRegExp(/fred/);
+     * // => true
+     */
+    function isRegExp(value) {
+      return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false;
+    }
+
+    /**
+     * Checks if `value` is a string.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
+     * @example
+     *
+     * _.isString('fred');
+     * // => true
+     */
+    function isString(value) {
+      return typeof value == 'string' ||
+        value && typeof value == 'object' && toString.call(value) == stringClass || false;
+    }
+
+    /**
+     * Checks if `value` is `undefined`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
+     * @example
+     *
+     * _.isUndefined(void 0);
+     * // => true
+     */
+    function isUndefined(value) {
+      return typeof value == 'undefined';
+    }
+
+    /**
+     * Creates an object with the same keys as `object` and values generated by
+     * running each own enumerable property of `object` through the callback.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new object with values of the results of each `callback` execution.
+     * @example
+     *
+     * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     *
+     * var characters = {
+     *   'fred': { 'name': 'fred', 'age': 40 },
+     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.mapValues(characters, 'age');
+     * // => { 'fred': 40, 'pebbles': 1 }
+     */
+    function mapValues(object, callback, thisArg) {
+      var result = {};
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      forOwn(object, function(value, key, object) {
+        result[key] = callback(value, key, object);
+      });
+      return result;
+    }
+
+    /**
+     * Recursively merges own enumerable properties of the source object(s), that
+     * don't resolve to `undefined` into the destination object. Subsequent sources
+     * will overwrite property assignments of previous sources. If a callback is
+     * provided it will be executed to produce the merged values of the destination
+     * and source properties. If the callback returns `undefined` merging will
+     * be handled by the method instead. The callback is bound to `thisArg` and
+     * invoked with two arguments; (objectValue, sourceValue).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param {Function} [callback] The function to customize merging properties.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * var names = {
+     *   'characters': [
+     *     { 'name': 'barney' },
+     *     { 'name': 'fred' }
+     *   ]
+     * };
+     *
+     * var ages = {
+     *   'characters': [
+     *     { 'age': 36 },
+     *     { 'age': 40 }
+     *   ]
+     * };
+     *
+     * _.merge(names, ages);
+     * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
+     *
+     * var food = {
+     *   'fruits': ['apple'],
+     *   'vegetables': ['beet']
+     * };
+     *
+     * var otherFood = {
+     *   'fruits': ['banana'],
+     *   'vegetables': ['carrot']
+     * };
+     *
+     * _.merge(food, otherFood, function(a, b) {
+     *   return _.isArray(a) ? a.concat(b) : undefined;
+     * });
+     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+     */
+    function merge(object) {
+      var args = arguments,
+          length = 2;
+
+      if (!isObject(object)) {
+        return object;
+      }
+      // allows working with `_.reduce` and `_.reduceRight` without using
+      // their `index` and `collection` arguments
+      if (typeof args[2] != 'number') {
+        length = args.length;
+      }
+      if (length > 3 && typeof args[length - 2] == 'function') {
+        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
+      } else if (length > 2 && typeof args[length - 1] == 'function') {
+        callback = args[--length];
+      }
+      var sources = slice(arguments, 1, length),
+          index = -1,
+          stackA = getArray(),
+          stackB = getArray();
+
+      while (++index < length) {
+        baseMerge(object, sources[index], callback, stackA, stackB);
+      }
+      releaseArray(stackA);
+      releaseArray(stackB);
+      return object;
+    }
+
+    /**
+     * Creates a shallow clone of `object` excluding the specified properties.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If a callback is provided it will be executed for each
+     * property of `object` omitting the properties the callback returns truey
+     * for. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The source object.
+     * @param {Function|...string|string[]} [callback] The properties to omit or the
+     *  function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns an object without the omitted properties.
+     * @example
+     *
+     * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
+     * // => { 'name': 'fred' }
+     *
+     * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
+     *   return typeof value == 'number';
+     * });
+     * // => { 'name': 'fred' }
+     */
+    function omit(object, callback, thisArg) {
+      var result = {};
+      if (typeof callback != 'function') {
+        var props = [];
+        forIn(object, function(value, key) {
+          props.push(key);
+        });
+        props = baseDifference(props, baseFlatten(arguments, true, false, 1));
+
+        var index = -1,
+            length = props.length;
+
+        while (++index < length) {
+          var key = props[index];
+          result[key] = object[key];
+        }
+      } else {
+        callback = lodash.createCallback(callback, thisArg, 3);
+        forIn(object, function(value, key, object) {
+          if (!callback(value, key, object)) {
+            result[key] = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Creates a two dimensional array of an object's key-value pairs,
+     * i.e. `[[key1, value1], [key2, value2]]`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns new array of key-value pairs.
+     * @example
+     *
+     * _.pairs({ 'barney': 36, 'fred': 40 });
+     * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
+     */
+    function pairs(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        var key = props[index];
+        result[index] = [key, object[key]];
+      }
+      return result;
+    }
+
+    /**
+     * Creates a shallow clone of `object` composed of the specified properties.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If a callback is provided it will be executed for each
+     * property of `object` picking the properties the callback returns truey
+     * for. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The source object.
+     * @param {Function|...string|string[]} [callback] The function called per
+     *  iteration or property names to pick, specified as individual property
+     *  names or arrays of property names.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns an object composed of the picked properties.
+     * @example
+     *
+     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
+     * // => { 'name': 'fred' }
+     *
+     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
+     *   return key.charAt(0) != '_';
+     * });
+     * // => { 'name': 'fred' }
+     */
+    function pick(object, callback, thisArg) {
+      var result = {};
+      if (typeof callback != 'function') {
+        var index = -1,
+            props = baseFlatten(arguments, true, false, 1),
+            length = isObject(object) ? props.length : 0;
+
+        while (++index < length) {
+          var key = props[index];
+          if (key in object) {
+            result[key] = object[key];
+          }
+        }
+      } else {
+        callback = lodash.createCallback(callback, thisArg, 3);
+        forIn(object, function(value, key, object) {
+          if (callback(value, key, object)) {
+            result[key] = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * An alternative to `_.reduce` this method transforms `object` to a new
+     * `accumulator` object which is the result of running each of its own
+     * enumerable properties through a callback, with each callback execution
+     * potentially mutating the `accumulator` object. The callback is bound to
+     * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
+     * Callbacks may exit iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Array|Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] The custom accumulator value.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
+     *   num *= num;
+     *   if (num % 2) {
+     *     return result.push(num) < 3;
+     *   }
+     * });
+     * // => [1, 9, 25]
+     *
+     * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+     *   result[key] = num * 3;
+     * });
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     */
+    function transform(object, callback, accumulator, thisArg) {
+      var isArr = isArray(object);
+      if (accumulator == null) {
+        if (isArr) {
+          accumulator = [];
+        } else {
+          var ctor = object && object.constructor,
+              proto = ctor && ctor.prototype;
+
+          accumulator = baseCreate(proto);
+        }
+      }
+      if (callback) {
+        callback = lodash.createCallback(callback, thisArg, 4);
+        (isArr ? baseEach : forOwn)(object, function(value, index, object) {
+          return callback(accumulator, value, index, object);
+        });
+      }
+      return accumulator;
+    }
+
+    /**
+     * Creates an array composed of the own enumerable property values of `object`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property values.
+     * @example
+     *
+     * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => [1, 2, 3] (property order is not guaranteed across environments)
+     */
+    function values(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = object[props[index]];
+      }
+      return result;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array of elements from the specified indexes, or keys, of the
+     * `collection`. Indexes may be specified as individual arguments or as arrays
+     * of indexes.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
+     *   to retrieve, specified as individual indexes or arrays of indexes.
+     * @returns {Array} Returns a new array of elements corresponding to the
+     *  provided indexes.
+     * @example
+     *
+     * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+     * // => ['a', 'c', 'e']
+     *
+     * _.at(['fred', 'barney', 'pebbles'], 0, 2);
+     * // => ['fred', 'pebbles']
+     */
+    function at(collection) {
+      var args = arguments,
+          index = -1,
+          props = baseFlatten(args, true, false, 1),
+          length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
+          result = Array(length);
+
+      if (support.unindexedChars && isString(collection)) {
+        collection = collection.split('');
+      }
+      while(++index < length) {
+        result[index] = collection[props[index]];
+      }
+      return result;
+    }
+
+    /**
+     * Checks if a given value is present in a collection using strict equality
+     * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
+     * offset from the end of the collection.
+     *
+     * @static
+     * @memberOf _
+     * @alias include
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {*} target The value to check for.
+     * @param {number} [fromIndex=0] The index to search from.
+     * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
+     * @example
+     *
+     * _.contains([1, 2, 3], 1);
+     * // => true
+     *
+     * _.contains([1, 2, 3], 1, 2);
+     * // => false
+     *
+     * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
+     * // => true
+     *
+     * _.contains('pebbles', 'eb');
+     * // => true
+     */
+    function contains(collection, target, fromIndex) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = collection ? collection.length : 0,
+          result = false;
+
+      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+      if (isArray(collection)) {
+        result = indexOf(collection, target, fromIndex) > -1;
+      } else if (typeof length == 'number') {
+        result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
+      } else {
+        baseEach(collection, function(value) {
+          if (++index >= fromIndex) {
+            return !(result = value === target);
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of `collection` through the callback. The corresponding value
+     * of each key is the number of times the key was returned by the callback.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy(['one', 'two', 'three'], 'length');
+     * // => { '3': 2, '5': 1 }
+     */
+    var countBy = createAggregator(function(result, value, key) {
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+
+    /**
+     * Checks if the given callback returns truey value for **all** elements of
+     * a collection. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias all
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if all elements passed the callback check,
+     *  else `false`.
+     * @example
+     *
+     * _.every([true, 1, null, 'yes']);
+     * // => false
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.every(characters, 'age');
+     * // => true
+     *
+     * // using "_.where" callback shorthand
+     * _.every(characters, { 'age': 36 });
+     * // => false
+     */
+    function every(collection, callback, thisArg) {
+      var result = true;
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          if (!(result = !!callback(collection[index], index, collection))) {
+            break;
+          }
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          return (result = !!callback(value, index, collection));
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, returning an array of all elements
+     * the callback returns truey for. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias select
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of elements that passed the callback check.
+     * @example
+     *
+     * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+     * // => [2, 4, 6]
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.filter(characters, 'blocked');
+     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+     *
+     * // using "_.where" callback shorthand
+     * _.filter(characters, { 'age': 36 });
+     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+     */
+    function filter(collection, callback, thisArg) {
+      var result = [];
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (callback(value, index, collection)) {
+            result.push(value);
+          }
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          if (callback(value, index, collection)) {
+            result.push(value);
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, returning the first element that
+     * the callback returns truey for. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias detect, findWhere
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the found element, else `undefined`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': false },
+     *   { 'name': 'fred',    'age': 40, 'blocked': true },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+     * ];
+     *
+     * _.find(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => { 'name': 'barney', 'age': 36, 'blocked': false }
+     *
+     * // using "_.where" callback shorthand
+     * _.find(characters, { 'age': 1 });
+     * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
+     *
+     * // using "_.pluck" callback shorthand
+     * _.find(characters, 'blocked');
+     * // => { 'name': 'fred', 'age': 40, 'blocked': true }
+     */
+    function find(collection, callback, thisArg) {
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (callback(value, index, collection)) {
+            return value;
+          }
+        }
+      } else {
+        var result;
+        baseEach(collection, function(value, index, collection) {
+          if (callback(value, index, collection)) {
+            result = value;
+            return false;
+          }
+        });
+        return result;
+      }
+    }
+
+    /**
+     * This method is like `_.find` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the found element, else `undefined`.
+     * @example
+     *
+     * _.findLast([1, 2, 3, 4], function(num) {
+     *   return num % 2 == 1;
+     * });
+     * // => 3
+     */
+    function findLast(collection, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forEachRight(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result = value;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, executing the callback for each
+     * element. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection). Callbacks may exit iteration early by
+     * explicitly returning `false`.
+     *
+     * Note: As with other "Collections" methods, objects with a `length` property
+     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+     * may be used for object iteration.
+     *
+     * @static
+     * @memberOf _
+     * @alias each
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
+     * // => logs each number and returns '1,2,3'
+     *
+     * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+     * // => logs each number and returns the object (property order is not guaranteed across environments)
+     */
+    function forEach(collection, callback, thisArg) {
+      if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          if (callback(collection[index], index, collection) === false) {
+            break;
+          }
+        }
+      } else {
+        baseEach(collection, callback, thisArg);
+      }
+      return collection;
+    }
+
+    /**
+     * This method is like `_.forEach` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias eachRight
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
+     * // => logs each number from right to left and returns '3,2,1'
+     */
+    function forEachRight(collection, callback, thisArg) {
+      var iterable = collection,
+          length = collection ? collection.length : 0;
+
+      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+      if (isArray(collection)) {
+        while (length--) {
+          if (callback(collection[length], length, collection) === false) {
+            break;
+          }
+        }
+      } else {
+        if (typeof length != 'number') {
+          var props = keys(collection);
+          length = props.length;
+        } else if (support.unindexedChars && isString(collection)) {
+          iterable = collection.split('');
+        }
+        baseEach(collection, function(value, key, collection) {
+          key = props ? props[--length] : --length;
+          return callback(iterable[key], key, collection);
+        });
+      }
+      return collection;
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of a collection through the callback. The corresponding value
+     * of each key is an array of the elements responsible for generating the key.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * // using "_.pluck" callback shorthand
+     * _.groupBy(['one', 'two', 'three'], 'length');
+     * // => { '3': ['one', 'two'], '5': ['three'] }
+     */
+    var groupBy = createAggregator(function(result, value, key) {
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of the collection through the given callback. The corresponding
+     * value of each key is the last element responsible for generating the key.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * var keys = [
+     *   { 'dir': 'left', 'code': 97 },
+     *   { 'dir': 'right', 'code': 100 }
+     * ];
+     *
+     * _.indexBy(keys, 'dir');
+     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     */
+    var indexBy = createAggregator(function(result, value, key) {
+      result[key] = value;
+    });
+
+    /**
+     * Invokes the method named by `methodName` on each element in the `collection`
+     * returning an array of the results of each invoked method. Additional arguments
+     * will be provided to each invoked method. If `methodName` is a function it
+     * will be invoked for, and `this` bound to, each element in the `collection`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|string} methodName The name of the method to invoke or
+     *  the function invoked per iteration.
+     * @param {...*} [arg] Arguments to invoke the method with.
+     * @returns {Array} Returns a new array of the results of each invoked method.
+     * @example
+     *
+     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+     * // => [[1, 5, 7], [1, 2, 3]]
+     *
+     * _.invoke([123, 456], String.prototype.split, '');
+     * // => [['1', '2', '3'], ['4', '5', '6']]
+     */
+    function invoke(collection, methodName) {
+      var args = slice(arguments, 2),
+          index = -1,
+          isFunc = typeof methodName == 'function',
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      forEach(collection, function(value) {
+        result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+      });
+      return result;
+    }
+
+    /**
+     * Creates an array of values by running each element in the collection
+     * through the callback. The callback is bound to `thisArg` and invoked with
+     * three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias collect
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of the results of each `callback` execution.
+     * @example
+     *
+     * _.map([1, 2, 3], function(num) { return num * 3; });
+     * // => [3, 6, 9]
+     *
+     * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+     * // => [3, 6, 9] (property order is not guaranteed across environments)
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.map(characters, 'name');
+     * // => ['barney', 'fred']
+     */
+    function map(collection, callback, thisArg) {
+      var index = -1,
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      if (isArray(collection)) {
+        while (++index < length) {
+          result[index] = callback(collection[index], index, collection);
+        }
+      } else {
+        baseEach(collection, function(value, key, collection) {
+          result[++index] = callback(value, key, collection);
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the maximum value of a collection. If the collection is empty or
+     * falsey `-Infinity` is returned. If a callback is provided it will be executed
+     * for each value in the collection to generate the criterion by which the value
+     * is ranked. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the maximum value.
+     * @example
+     *
+     * _.max([4, 2, 8, 6]);
+     * // => 8
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.max(characters, function(chr) { return chr.age; });
+     * // => { 'name': 'fred', 'age': 40 };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.max(characters, 'age');
+     * // => { 'name': 'fred', 'age': 40 };
+     */
+    function max(collection, callback, thisArg) {
+      var computed = -Infinity,
+          result = computed;
+
+      // allows working with functions like `_.map` without using
+      // their `index` argument as a callback
+      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+        callback = null;
+      }
+      if (callback == null && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (value > result) {
+            result = value;
+          }
+        }
+      } else {
+        callback = (callback == null && isString(collection))
+          ? charAtCallback
+          : lodash.createCallback(callback, thisArg, 3);
+
+        baseEach(collection, function(value, index, collection) {
+          var current = callback(value, index, collection);
+          if (current > computed) {
+            computed = current;
+            result = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the minimum value of a collection. If the collection is empty or
+     * falsey `Infinity` is returned. If a callback is provided it will be executed
+     * for each value in the collection to generate the criterion by which the value
+     * is ranked. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the minimum value.
+     * @example
+     *
+     * _.min([4, 2, 8, 6]);
+     * // => 2
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.min(characters, function(chr) { return chr.age; });
+     * // => { 'name': 'barney', 'age': 36 };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.min(characters, 'age');
+     * // => { 'name': 'barney', 'age': 36 };
+     */
+    function min(collection, callback, thisArg) {
+      var computed = Infinity,
+          result = computed;
+
+      // allows working with functions like `_.map` without using
+      // their `index` argument as a callback
+      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+        callback = null;
+      }
+      if (callback == null && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (value < result) {
+            result = value;
+          }
+        }
+      } else {
+        callback = (callback == null && isString(collection))
+          ? charAtCallback
+          : lodash.createCallback(callback, thisArg, 3);
+
+        baseEach(collection, function(value, index, collection) {
+          var current = callback(value, index, collection);
+          if (current < computed) {
+            computed = current;
+            result = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the value of a specified property from all elements in the collection.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {string} property The name of the property to pluck.
+     * @returns {Array} Returns a new array of property values.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.pluck(characters, 'name');
+     * // => ['barney', 'fred']
+     */
+    var pluck = map;
+
+    /**
+     * Reduces a collection to a value which is the accumulated result of running
+     * each element in the collection through the callback, where each successive
+     * callback execution consumes the return value of the previous execution. If
+     * `accumulator` is not provided the first element of the collection will be
+     * used as the initial `accumulator` value. The callback is bound to `thisArg`
+     * and invoked with four arguments; (accumulator, value, index|key, collection).
+     *
+     * @static
+     * @memberOf _
+     * @alias foldl, inject
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] Initial value of the accumulator.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var sum = _.reduce([1, 2, 3], function(sum, num) {
+     *   return sum + num;
+     * });
+     * // => 6
+     *
+     * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+     *   result[key] = num * 3;
+     *   return result;
+     * }, {});
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     */
+    function reduce(collection, callback, accumulator, thisArg) {
+      var noaccum = arguments.length < 3;
+      callback = lodash.createCallback(callback, thisArg, 4);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        if (noaccum) {
+          accumulator = collection[++index];
+        }
+        while (++index < length) {
+          accumulator = callback(accumulator, collection[index], index, collection);
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          accumulator = noaccum
+            ? (noaccum = false, value)
+            : callback(accumulator, value, index, collection)
+        });
+      }
+      return accumulator;
+    }
+
+    /**
+     * This method is like `_.reduce` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias foldr
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] Initial value of the accumulator.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var list = [[0, 1], [2, 3], [4, 5]];
+     * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+     * // => [4, 5, 2, 3, 0, 1]
+     */
+    function reduceRight(collection, callback, accumulator, thisArg) {
+      var noaccum = arguments.length < 3;
+      callback = lodash.createCallback(callback, thisArg, 4);
+      forEachRight(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection);
+      });
+      return accumulator;
+    }
+
+    /**
+     * The opposite of `_.filter` this method returns the elements of a
+     * collection that the callback does **not** return truey for.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of elements that failed the callback check.
+     * @example
+     *
+     * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+     * // => [1, 3, 5]
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.reject(characters, 'blocked');
+     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+     *
+     * // using "_.where" callback shorthand
+     * _.reject(characters, { 'age': 36 });
+     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+     */
+    function reject(collection, callback, thisArg) {
+      callback = lodash.createCallback(callback, thisArg, 3);
+      return filter(collection, function(value, index, collection) {
+        return !callback(value, index, collection);
+      });
+    }
+
+    /**
+     * Retrieves a random element or `n` random elements from a collection.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to sample.
+     * @param {number} [n] The number of elements to sample.
+     * @param- {Object} [guard] Allows working with functions like `_.map`
+     *  without using their `index` arguments as `n`.
+     * @returns {Array} Returns the random sample(s) of `collection`.
+     * @example
+     *
+     * _.sample([1, 2, 3, 4]);
+     * // => 2
+     *
+     * _.sample([1, 2, 3, 4], 2);
+     * // => [3, 1]
+     */
+    function sample(collection, n, guard) {
+      if (collection && typeof collection.length != 'number') {
+        collection = values(collection);
+      } else if (support.unindexedChars && isString(collection)) {
+        collection = collection.split('');
+      }
+      if (n == null || guard) {
+        return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
+      }
+      var result = shuffle(collection);
+      result.length = nativeMin(nativeMax(0, n), result.length);
+      return result;
+    }
+
+    /**
+     * Creates an array of shuffled values, using a version of the Fisher-Yates
+     * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to shuffle.
+     * @returns {Array} Returns a new shuffled collection.
+     * @example
+     *
+     * _.shuffle([1, 2, 3, 4, 5, 6]);
+     * // => [4, 1, 6, 3, 5, 2]
+     */
+    function shuffle(collection) {
+      var index = -1,
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      forEach(collection, function(value) {
+        var rand = baseRandom(0, ++index);
+        result[index] = result[rand];
+        result[rand] = value;
+      });
+      return result;
+    }
+
+    /**
+     * Gets the size of the `collection` by returning `collection.length` for arrays
+     * and array-like objects or the number of own enumerable properties for objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to inspect.
+     * @returns {number} Returns `collection.length` or number of own enumerable properties.
+     * @example
+     *
+     * _.size([1, 2]);
+     * // => 2
+     *
+     * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => 3
+     *
+     * _.size('pebbles');
+     * // => 7
+     */
+    function size(collection) {
+      var length = collection ? collection.length : 0;
+      return typeof length == 'number' ? length : keys(collection).length;
+    }
+
+    /**
+     * Checks if the callback returns a truey value for **any** element of a
+     * collection. The function returns as soon as it finds a passing value and
+     * does not iterate over the entire collection. The callback is bound to
+     * `thisArg` and invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias any
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if any element passed the callback check,
+     *  else `false`.
+     * @example
+     *
+     * _.some([null, 0, 'yes', false], Boolean);
+     * // => true
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.some(characters, 'blocked');
+     * // => true
+     *
+     * // using "_.where" callback shorthand
+     * _.some(characters, { 'age': 1 });
+     * // => false
+     */
+    function some(collection, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          if ((result = callback(collection[index], index, collection))) {
+            break;
+          }
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          return !(result = callback(value, index, collection));
+        });
+      }
+      return !!result;
+    }
+
+    /**
+     * Creates an array of elements, sorted in ascending order by the results of
+     * running each element in a collection through the callback. This method
+     * performs a stable sort, that is, it will preserve the original sort order
+     * of equal elements. The callback is bound to `thisArg` and invoked with
+     * three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an array of property names is provided for `callback` the collection
+     * will be sorted by each property value.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Array|Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of sorted elements.
+     * @example
+     *
+     * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+     * // => [3, 1, 2]
+     *
+     * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+     * // => [3, 1, 2]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36 },
+     *   { 'name': 'fred',    'age': 40 },
+     *   { 'name': 'barney',  'age': 26 },
+     *   { 'name': 'fred',    'age': 30 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.map(_.sortBy(characters, 'age'), _.values);
+     * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
+     *
+     * // sorting by multiple properties
+     * _.map(_.sortBy(characters, ['name', 'age']), _.values);
+     * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
+     */
+    function sortBy(collection, callback, thisArg) {
+      var index = -1,
+          isArr = isArray(callback),
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      if (!isArr) {
+        callback = lodash.createCallback(callback, thisArg, 3);
+      }
+      forEach(collection, function(value, key, collection) {
+        var object = result[++index] = getObject();
+        if (isArr) {
+          object.criteria = map(callback, function(key) { return value[key]; });
+        } else {
+          (object.criteria = getArray())[0] = callback(value, key, collection);
+        }
+        object.index = index;
+        object.value = value;
+      });
+
+      length = result.length;
+      result.sort(compareAscending);
+      while (length--) {
+        var object = result[length];
+        result[length] = object.value;
+        if (!isArr) {
+          releaseArray(object.criteria);
+        }
+        releaseObject(object);
+      }
+      return result;
+    }
+
+    /**
+     * Converts the `collection` to an array.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to convert.
+     * @returns {Array} Returns the new converted array.
+     * @example
+     *
+     * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+     * // => [2, 3, 4]
+     */
+    function toArray(collection) {
+      if (collection && typeof collection.length == 'number') {
+        return (support.unindexedChars && isString(collection))
+          ? collection.split('')
+          : slice(collection);
+      }
+      return values(collection);
+    }
+
+    /**
+     * Performs a deep comparison of each element in a `collection` to the given
+     * `properties` object, returning an array of all elements that have equivalent
+     * property values.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Object} props The object of property values to filter by.
+     * @returns {Array} Returns a new array of elements that have the given properties.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
+     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * _.where(characters, { 'age': 36 });
+     * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
+     *
+     * _.where(characters, { 'pets': ['dino'] });
+     * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
+     */
+    var where = filter;
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array with all falsey values removed. The values `false`, `null`,
+     * `0`, `""`, `undefined`, and `NaN` are all falsey.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to compact.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.compact([0, 1, false, 2, '', 3]);
+     * // => [1, 2, 3]
+     */
+    function compact(array) {
+      var index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+        if (value) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array excluding all values of the provided arrays using strict
+     * equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to process.
+     * @param {...Array} [values] The arrays of values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+     * // => [1, 3, 4]
+     */
+    function difference(array) {
+      return baseDifference(array, baseFlatten(arguments, true, true, 1));
+    }
+
+    /**
+     * This method is like `_.find` except that it returns the index of the first
+     * element that passes the callback check, instead of the element itself.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': false },
+     *   { 'name': 'fred',    'age': 40, 'blocked': true },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+     * ];
+     *
+     * _.findIndex(characters, function(chr) {
+     *   return chr.age < 20;
+     * });
+     * // => 2
+     *
+     * // using "_.where" callback shorthand
+     * _.findIndex(characters, { 'age': 36 });
+     * // => 0
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findIndex(characters, 'blocked');
+     * // => 1
+     */
+    function findIndex(array, callback, thisArg) {
+      var index = -1,
+          length = array ? array.length : 0;
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (++index < length) {
+        if (callback(array[index], index, array)) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * This method is like `_.findIndex` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': true },
+     *   { 'name': 'fred',    'age': 40, 'blocked': false },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
+     * ];
+     *
+     * _.findLastIndex(characters, function(chr) {
+     *   return chr.age > 30;
+     * });
+     * // => 1
+     *
+     * // using "_.where" callback shorthand
+     * _.findLastIndex(characters, { 'age': 36 });
+     * // => 0
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findLastIndex(characters, 'blocked');
+     * // => 2
+     */
+    function findLastIndex(array, callback, thisArg) {
+      var length = array ? array.length : 0;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (length--) {
+        if (callback(array[length], length, array)) {
+          return length;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Gets the first element or first `n` elements of an array. If a callback
+     * is provided elements at the beginning of the array are returned as long
+     * as the callback returns truey. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias head, take
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback] The function called
+     *  per element or the number of elements to return. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the first element(s) of `array`.
+     * @example
+     *
+     * _.first([1, 2, 3]);
+     * // => 1
+     *
+     * _.first([1, 2, 3], 2);
+     * // => [1, 2]
+     *
+     * _.first([1, 2, 3], function(num) {
+     *   return num < 3;
+     * });
+     * // => [1, 2]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.first(characters, 'blocked');
+     * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
+     *
+     * // using "_.where" callback shorthand
+     * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
+     * // => ['barney', 'fred']
+     */
+    function first(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array ? array[0] : undefined;
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+
+    /**
+     * Flattens a nested array (the nesting can be to any depth). If `isShallow`
+     * is truey, the array will only be flattened a single level. If a callback
+     * is provided each element of the array is passed through the callback before
+     * flattening. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new flattened array.
+     * @example
+     *
+     * _.flatten([1, [2], [3, [[4]]]]);
+     * // => [1, 2, 3, 4];
+     *
+     * _.flatten([1, [2], [3, [[4]]]], true);
+     * // => [1, 2, 3, [[4]]];
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
+     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.flatten(characters, 'pets');
+     * // => ['hoppy', 'baby puss', 'dino']
+     */
+    function flatten(array, isShallow, callback, thisArg) {
+      // juggle arguments
+      if (typeof isShallow != 'boolean' && isShallow != null) {
+        thisArg = callback;
+        callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
+        isShallow = false;
+      }
+      if (callback != null) {
+        array = map(array, callback, thisArg);
+      }
+      return baseFlatten(array, isShallow);
+    }
+
+    /**
+     * Gets the index at which the first occurrence of `value` is found using
+     * strict equality for comparisons, i.e. `===`. If the array is already sorted
+     * providing `true` for `fromIndex` will run a faster binary search.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+     *  to perform a binary search on a sorted array.
+     * @returns {number} Returns the index of the matched value or `-1`.
+     * @example
+     *
+     * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+     * // => 1
+     *
+     * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+     * // => 4
+     *
+     * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+     * // => 2
+     */
+    function indexOf(array, value, fromIndex) {
+      if (typeof fromIndex == 'number') {
+        var length = array ? array.length : 0;
+        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
+      } else if (fromIndex) {
+        var index = sortedIndex(array, value);
+        return array[index] === value ? index : -1;
+      }
+      return baseIndexOf(array, value, fromIndex);
+    }
+
+    /**
+     * Gets all but the last element or last `n` elements of an array. If a
+     * callback is provided elements at the end of the array are excluded from
+     * the result as long as the callback returns truey. The callback is bound
+     * to `thisArg` and invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback=1] The function called
+     *  per element or the number of elements to exclude. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a slice of `array`.
+     * @example
+     *
+     * _.initial([1, 2, 3]);
+     * // => [1, 2]
+     *
+     * _.initial([1, 2, 3], 2);
+     * // => [1]
+     *
+     * _.initial([1, 2, 3], function(num) {
+     *   return num > 1;
+     * });
+     * // => [1]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.initial(characters, 'blocked');
+     * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
+     *
+     * // using "_.where" callback shorthand
+     * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
+     * // => ['barney', 'fred']
+     */
+    function initial(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = (callback == null || thisArg) ? 1 : callback || n;
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+    }
+
+    /**
+     * Creates an array of unique values present in all provided arrays using
+     * strict equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of shared values.
+     * @example
+     *
+     * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+     * // => [1, 2]
+     */
+    function intersection() {
+      var args = [],
+          argsIndex = -1,
+          argsLength = arguments.length,
+          caches = getArray(),
+          indexOf = getIndexOf(),
+          trustIndexOf = indexOf === baseIndexOf,
+          seen = getArray();
+
+      while (++argsIndex < argsLength) {
+        var value = arguments[argsIndex];
+        if (isArray(value) || isArguments(value)) {
+          args.push(value);
+          caches.push(trustIndexOf && value.length >= largeArraySize &&
+            createCache(argsIndex ? args[argsIndex] : seen));
+        }
+      }
+      var array = args[0],
+          index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      outer:
+      while (++index < length) {
+        var cache = caches[0];
+        value = array[index];
+
+        if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
+          argsIndex = argsLength;
+          (cache || seen).push(value);
+          while (--argsIndex) {
+            cache = caches[argsIndex];
+            if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
+              continue outer;
+            }
+          }
+          result.push(value);
+        }
+      }
+      while (argsLength--) {
+        cache = caches[argsLength];
+        if (cache) {
+          releaseObject(cache);
+        }
+      }
+      releaseArray(caches);
+      releaseArray(seen);
+      return result;
+    }
+
+    /**
+     * Gets the last element or last `n` elements of an array. If a callback is
+     * provided elements at the end of the array are returned as long as the
+     * callback returns truey. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback] The function called
+     *  per element or the number of elements to return. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the last element(s) of `array`.
+     * @example
+     *
+     * _.last([1, 2, 3]);
+     * // => 3
+     *
+     * _.last([1, 2, 3], 2);
+     * // => [2, 3]
+     *
+     * _.last([1, 2, 3], function(num) {
+     *   return num > 1;
+     * });
+     * // => [2, 3]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.pluck(_.last(characters, 'blocked'), 'name');
+     * // => ['fred', 'pebbles']
+     *
+     * // using "_.where" callback shorthand
+     * _.last(characters, { 'employer': 'na' });
+     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+     */
+    function last(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array ? array[length - 1] : undefined;
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+
+    /**
+     * Gets the index at which the last occurrence of `value` is found using strict
+     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+     * as the offset from the end of the collection.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {number} [fromIndex=array.length-1] The index to search from.
+     * @returns {number} Returns the index of the matched value or `-1`.
+     * @example
+     *
+     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+     * // => 4
+     *
+     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+     * // => 1
+     */
+    function lastIndexOf(array, value, fromIndex) {
+      var index = array ? array.length : 0;
+      if (typeof fromIndex == 'number') {
+        index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+      }
+      while (index--) {
+        if (array[index] === value) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Removes all provided values from the given array using strict equality for
+     * comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to modify.
+     * @param {...*} [value] The values to remove.
+     * @returns {Array} Returns `array`.
+     * @example
+     *
+     * var array = [1, 2, 3, 1, 2, 3];
+     * _.pull(array, 2, 3);
+     * console.log(array);
+     * // => [1, 1]
+     */
+    function pull(array) {
+      var args = arguments,
+          argsIndex = 0,
+          argsLength = args.length,
+          length = array ? array.length : 0;
+
+      while (++argsIndex < argsLength) {
+        var index = -1,
+            value = args[argsIndex];
+        while (++index < length) {
+          if (array[index] === value) {
+            splice.call(array, index--, 1);
+            length--;
+          }
+        }
+      }
+      return array;
+    }
+
+    /**
+     * Creates an array of numbers (positive and/or negative) progressing from
+     * `start` up to but not including `end`. If `start` is less than `stop` a
+     * zero-length range is created unless a negative `step` is specified.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {number} [start=0] The start of the range.
+     * @param {number} end The end of the range.
+     * @param {number} [step=1] The value to increment or decrement by.
+     * @returns {Array} Returns a new range array.
+     * @example
+     *
+     * _.range(4);
+     * // => [0, 1, 2, 3]
+     *
+     * _.range(1, 5);
+     * // => [1, 2, 3, 4]
+     *
+     * _.range(0, 20, 5);
+     * // => [0, 5, 10, 15]
+     *
+     * _.range(0, -4, -1);
+     * // => [0, -1, -2, -3]
+     *
+     * _.range(1, 4, 0);
+     * // => [1, 1, 1]
+     *
+     * _.range(0);
+     * // => []
+     */
+    function range(start, end, step) {
+      start = +start || 0;
+      step = typeof step == 'number' ? step : (+step || 1);
+
+      if (end == null) {
+        end = start;
+        start = 0;
+      }
+      // use `Array(length)` so engines like Chakra and V8 avoid slower modes
+      // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+      var index = -1,
+          length = nativeMax(0, ceil((end - start) / (step || 1))),
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = start;
+        start += step;
+      }
+      return result;
+    }
+
+    /**
+     * Removes all elements from an array that the callback returns truey for
+     * and returns an array of removed elements. The callback is bound to `thisArg`
+     * and invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to modify.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of removed elements.
+     * @example
+     *
+     * var array = [1, 2, 3, 4, 5, 6];
+     * var evens = _.remove(array, function(num) { return num % 2 == 0; });
+     *
+     * console.log(array);
+     * // => [1, 3, 5]
+     *
+     * console.log(evens);
+     * // => [2, 4, 6]
+     */
+    function remove(array, callback, thisArg) {
+      var index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (++index < length) {
+        var value = array[index];
+        if (callback(value, index, array)) {
+          result.push(value);
+          splice.call(array, index--, 1);
+          length--;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The opposite of `_.initial` this method gets all but the first element or
+     * first `n` elements of an array. If a callback function is provided elements
+     * at the beginning of the array are excluded from the result as long as the
+     * callback returns truey. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias drop, tail
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback=1] The function called
+     *  per element or the number of elements to exclude. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a slice of `array`.
+     * @example
+     *
+     * _.rest([1, 2, 3]);
+     * // => [2, 3]
+     *
+     * _.rest([1, 2, 3], 2);
+     * // => [3]
+     *
+     * _.rest([1, 2, 3], function(num) {
+     *   return num < 3;
+     * });
+     * // => [3]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.pluck(_.rest(characters, 'blocked'), 'name');
+     * // => ['fred', 'pebbles']
+     *
+     * // using "_.where" callback shorthand
+     * _.rest(characters, { 'employer': 'slate' });
+     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+     */
+    function rest(array, callback, thisArg) {
+      if (typeof callback != 'number' && callback != null) {
+        var n = 0,
+            index = -1,
+            length = array ? array.length : 0;
+
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+      }
+      return slice(array, n);
+    }
+
+    /**
+     * Uses a binary search to determine the smallest index at which a value
+     * should be inserted into a given sorted array in order to maintain the sort
+     * order of the array. If a callback is provided it will be executed for
+     * `value` and each element of `array` to compute their sort ranking. The
+     * callback is bound to `thisArg` and invoked with one argument; (value).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     * @example
+     *
+     * _.sortedIndex([20, 30, 50], 40);
+     * // => 2
+     *
+     * // using "_.pluck" callback shorthand
+     * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+     * // => 2
+     *
+     * var dict = {
+     *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+     * };
+     *
+     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+     *   return dict.wordToNumber[word];
+     * });
+     * // => 2
+     *
+     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+     *   return this.wordToNumber[word];
+     * }, dict);
+     * // => 2
+     */
+    function sortedIndex(array, value, callback, thisArg) {
+      var low = 0,
+          high = array ? array.length : low;
+
+      // explicitly reference `identity` for better inlining in Firefox
+      callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
+      value = callback(value);
+
+      while (low < high) {
+        var mid = (low + high) >>> 1;
+        (callback(array[mid]) < value)
+          ? low = mid + 1
+          : high = mid;
+      }
+      return low;
+    }
+
+    /**
+     * Creates an array of unique values, in order, of the provided arrays using
+     * strict equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of combined values.
+     * @example
+     *
+     * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+     * // => [1, 2, 3, 5, 4]
+     */
+    function union() {
+      return baseUniq(baseFlatten(arguments, true, true));
+    }
+
+    /**
+     * Creates a duplicate-value-free version of an array using strict equality
+     * for comparisons, i.e. `===`. If the array is sorted, providing
+     * `true` for `isSorted` will use a faster algorithm. If a callback is provided
+     * each element of `array` is passed through the callback before uniqueness
+     * is computed. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias unique
+     * @category Arrays
+     * @param {Array} array The array to process.
+     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a duplicate-value-free array.
+     * @example
+     *
+     * _.uniq([1, 2, 1, 3, 1]);
+     * // => [1, 2, 3]
+     *
+     * _.uniq([1, 1, 2, 2, 3], true);
+     * // => [1, 2, 3]
+     *
+     * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
+     * // => ['A', 'b', 'C']
+     *
+     * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+     * // => [1, 2.5, 3]
+     *
+     * // using "_.pluck" callback shorthand
+     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+     * // => [{ 'x': 1 }, { 'x': 2 }]
+     */
+    function uniq(array, isSorted, callback, thisArg) {
+      // juggle arguments
+      if (typeof isSorted != 'boolean' && isSorted != null) {
+        thisArg = callback;
+        callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
+        isSorted = false;
+      }
+      if (callback != null) {
+        callback = lodash.createCallback(callback, thisArg, 3);
+      }
+      return baseUniq(array, isSorted, callback);
+    }
+
+    /**
+     * Creates an array excluding all provided values using strict equality for
+     * comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to filter.
+     * @param {...*} [value] The values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+     * // => [2, 3, 4]
+     */
+    function without(array) {
+      return baseDifference(array, slice(arguments, 1));
+    }
+
+    /**
+     * Creates an array that is the symmetric difference of the provided arrays.
+     * See http://en.wikipedia.org/wiki/Symmetric_difference.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of values.
+     * @example
+     *
+     * _.xor([1, 2, 3], [5, 2, 1, 4]);
+     * // => [3, 5, 4]
+     *
+     * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
+     * // => [1, 4, 5]
+     */
+    function xor() {
+      var index = -1,
+          length = arguments.length;
+
+      while (++index < length) {
+        var array = arguments[index];
+        if (isArray(array) || isArguments(array)) {
+          var result = result
+            ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
+            : array;
+        }
+      }
+      return result || [];
+    }
+
+    /**
+     * Creates an array of grouped elements, the first of which contains the first
+     * elements of the given arrays, the second of which contains the second
+     * elements of the given arrays, and so on.
+     *
+     * @static
+     * @memberOf _
+     * @alias unzip
+     * @category Arrays
+     * @param {...Array} [array] Arrays to process.
+     * @returns {Array} Returns a new array of grouped elements.
+     * @example
+     *
+     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+     * // => [['fred', 30, true], ['barney', 40, false]]
+     */
+    function zip() {
+      var array = arguments.length > 1 ? arguments : arguments[0],
+          index = -1,
+          length = array ? max(pluck(array, 'length')) : 0,
+          result = Array(length < 0 ? 0 : length);
+
+      while (++index < length) {
+        result[index] = pluck(array, index);
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed from arrays of `keys` and `values`. Provide
+     * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
+     * or two arrays, one of `keys` and one of corresponding `values`.
+     *
+     * @static
+     * @memberOf _
+     * @alias object
+     * @category Arrays
+     * @param {Array} keys The array of keys.
+     * @param {Array} [values=[]] The array of values.
+     * @returns {Object} Returns an object composed of the given keys and
+     *  corresponding values.
+     * @example
+     *
+     * _.zipObject(['fred', 'barney'], [30, 40]);
+     * // => { 'fred': 30, 'barney': 40 }
+     */
+    function zipObject(keys, values) {
+      var index = -1,
+          length = keys ? keys.length : 0,
+          result = {};
+
+      if (!values && length && !isArray(keys[0])) {
+        values = [];
+      }
+      while (++index < length) {
+        var key = keys[index];
+        if (values) {
+          result[key] = values[index];
+        } else if (key) {
+          result[key[0]] = key[1];
+        }
+      }
+      return result;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a function that executes `func`, with  the `this` binding and
+     * arguments of the created function, only after being called `n` times.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {number} n The number of times the function must be called before
+     *  `func` is executed.
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var saves = ['profile', 'settings'];
+     *
+     * var done = _.after(saves.length, function() {
+     *   console.log('Done saving!');
+     * });
+     *
+     * _.forEach(saves, function(type) {
+     *   asyncSave({ 'type': type, 'complete': done });
+     * });
+     * // => logs 'Done saving!', after all saves have completed
+     */
+    function after(n, func) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      return function() {
+        if (--n < 1) {
+          return func.apply(this, arguments);
+        }
+      };
+    }
+
+    /**
+     * Creates a function that, when called, invokes `func` with the `this`
+     * binding of `thisArg` and prepends any additional `bind` arguments to those
+     * provided to the bound function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to bind.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var func = function(greeting) {
+     *   return greeting + ' ' + this.name;
+     * };
+     *
+     * func = _.bind(func, { 'name': 'fred' }, 'hi');
+     * func();
+     * // => 'hi fred'
+     */
+    function bind(func, thisArg) {
+      return arguments.length > 2
+        ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
+        : createWrapper(func, 1, null, null, thisArg);
+    }
+
+    /**
+     * Binds methods of an object to the object itself, overwriting the existing
+     * method. Method names may be specified as individual arguments or as arrays
+     * of method names. If no method names are provided all the function properties
+     * of `object` will be bound.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Object} object The object to bind and assign the bound methods to.
+     * @param {...string} [methodName] The object method names to
+     *  bind, specified as individual method names or arrays of method names.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'onClick': function() { console.log('clicked ' + this.label); }
+     * };
+     *
+     * _.bindAll(view);
+     * jQuery('#docs').on('click', view.onClick);
+     * // => logs 'clicked docs', when the button is clicked
+     */
+    function bindAll(object) {
+      var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
+          index = -1,
+          length = funcs.length;
+
+      while (++index < length) {
+        var key = funcs[index];
+        object[key] = createWrapper(object[key], 1, null, null, object);
+      }
+      return object;
+    }
+
+    /**
+     * Creates a function that, when called, invokes the method at `object[key]`
+     * and prepends any additional `bindKey` arguments to those provided to the bound
+     * function. This method differs from `_.bind` by allowing bound functions to
+     * reference methods that will be redefined or don't yet exist.
+     * See http://michaux.ca/articles/lazy-function-definition-pattern.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Object} object The object the method belongs to.
+     * @param {string} key The key of the method.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var object = {
+     *   'name': 'fred',
+     *   'greet': function(greeting) {
+     *     return greeting + ' ' + this.name;
+     *   }
+     * };
+     *
+     * var func = _.bindKey(object, 'greet', 'hi');
+     * func();
+     * // => 'hi fred'
+     *
+     * object.greet = function(greeting) {
+     *   return greeting + 'ya ' + this.name + '!';
+     * };
+     *
+     * func();
+     * // => 'hiya fred!'
+     */
+    function bindKey(object, key) {
+      return arguments.length > 2
+        ? createWrapper(key, 19, slice(arguments, 2), null, object)
+        : createWrapper(key, 3, null, null, object);
+    }
+
+    /**
+     * Creates a function that is the composition of the provided functions,
+     * where each function consumes the return value of the function that follows.
+     * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+     * Each function is executed with the `this` binding of the composed function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {...Function} [func] Functions to compose.
+     * @returns {Function} Returns the new composed function.
+     * @example
+     *
+     * var realNameMap = {
+     *   'pebbles': 'penelope'
+     * };
+     *
+     * var format = function(name) {
+     *   name = realNameMap[name.toLowerCase()] || name;
+     *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
+     * };
+     *
+     * var greet = function(formatted) {
+     *   return 'Hiya ' + formatted + '!';
+     * };
+     *
+     * var welcome = _.compose(greet, format);
+     * welcome('pebbles');
+     * // => 'Hiya Penelope!'
+     */
+    function compose() {
+      var funcs = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        if (!isFunction(funcs[length])) {
+          throw new TypeError;
+        }
+      }
+      return function() {
+        var args = arguments,
+            length = funcs.length;
+
+        while (length--) {
+          args = [funcs[length].apply(this, args)];
+        }
+        return args[0];
+      };
+    }
+
+    /**
+     * Creates a function which accepts one or more arguments of `func` that when
+     * invoked either executes `func` returning its result, if all `func` arguments
+     * have been provided, or returns a function that accepts one or more of the
+     * remaining `func` arguments, and so on. The arity of `func` can be specified
+     * if `func.length` is not sufficient.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to curry.
+     * @param {number} [arity=func.length] The arity of `func`.
+     * @returns {Function} Returns the new curried function.
+     * @example
+     *
+     * var curried = _.curry(function(a, b, c) {
+     *   console.log(a + b + c);
+     * });
+     *
+     * curried(1)(2)(3);
+     * // => 6
+     *
+     * curried(1, 2)(3);
+     * // => 6
+     *
+     * curried(1, 2, 3);
+     * // => 6
+     */
+    function curry(func, arity) {
+      arity = typeof arity == 'number' ? arity : (+arity || func.length);
+      return createWrapper(func, 4, null, null, null, arity);
+    }
+
+    /**
+     * Creates a function that will delay the execution of `func` until after
+     * `wait` milliseconds have elapsed since the last time it was invoked.
+     * Provide an options object to indicate that `func` should be invoked on
+     * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
+     * to the debounced function will return the result of the last `func` call.
+     *
+     * Note: If `leading` and `trailing` options are `true` `func` will be called
+     * on the trailing edge of the timeout only if the the debounced function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to debounce.
+     * @param {number} wait The number of milliseconds to delay.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
+     * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
+     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+     * @returns {Function} Returns the new debounced function.
+     * @example
+     *
+     * // avoid costly calculations while the window size is in flux
+     * var lazyLayout = _.debounce(calculateLayout, 150);
+     * jQuery(window).on('resize', lazyLayout);
+     *
+     * // execute `sendMail` when the click event is fired, debouncing subsequent calls
+     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+     *   'leading': true,
+     *   'trailing': false
+     * });
+     *
+     * // ensure `batchLog` is executed once after 1 second of debounced calls
+     * var source = new EventSource('/stream');
+     * source.addEventListener('message', _.debounce(batchLog, 250, {
+     *   'maxWait': 1000
+     * }, false);
+     */
+    function debounce(func, wait, options) {
+      var args,
+          maxTimeoutId,
+          result,
+          stamp,
+          thisArg,
+          timeoutId,
+          trailingCall,
+          lastCalled = 0,
+          maxWait = false,
+          trailing = true;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      wait = nativeMax(0, wait) || 0;
+      if (options === true) {
+        var leading = true;
+        trailing = false;
+      } else if (isObject(options)) {
+        leading = options.leading;
+        maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+      var delayed = function() {
+        var remaining = wait - (now() - stamp);
+        if (remaining <= 0) {
+          if (maxTimeoutId) {
+            clearTimeout(maxTimeoutId);
+          }
+          var isCalled = trailingCall;
+          maxTimeoutId = timeoutId = trailingCall = undefined;
+          if (isCalled) {
+            lastCalled = now();
+            result = func.apply(thisArg, args);
+            if (!timeoutId && !maxTimeoutId) {
+              args = thisArg = null;
+            }
+          }
+        } else {
+          timeoutId = setTimeout(delayed, remaining);
+        }
+      };
+
+      var maxDelayed = function() {
+        if (timeoutId) {
+          clearTimeout(timeoutId);
+        }
+        maxTimeoutId = timeoutId = trailingCall = undefined;
+        if (trailing || (maxWait !== wait)) {
+          lastCalled = now();
+          result = func.apply(thisArg, args);
+          if (!timeoutId && !maxTimeoutId) {
+            args = thisArg = null;
+          }
+        }
+      };
+
+      return function() {
+        args = arguments;
+        stamp = now();
+        thisArg = this;
+        trailingCall = trailing && (timeoutId || !leading);
+
+        if (maxWait === false) {
+          var leadingCall = leading && !timeoutId;
+        } else {
+          if (!maxTimeoutId && !leading) {
+            lastCalled = stamp;
+          }
+          var remaining = maxWait - (stamp - lastCalled),
+              isCalled = remaining <= 0;
+
+          if (isCalled) {
+            if (maxTimeoutId) {
+              maxTimeoutId = clearTimeout(maxTimeoutId);
+            }
+            lastCalled = stamp;
+            result = func.apply(thisArg, args);
+          }
+          else if (!maxTimeoutId) {
+            maxTimeoutId = setTimeout(maxDelayed, remaining);
+          }
+        }
+        if (isCalled && timeoutId) {
+          timeoutId = clearTimeout(timeoutId);
+        }
+        else if (!timeoutId && wait !== maxWait) {
+          timeoutId = setTimeout(delayed, wait);
+        }
+        if (leadingCall) {
+          isCalled = true;
+          result = func.apply(thisArg, args);
+        }
+        if (isCalled && !timeoutId && !maxTimeoutId) {
+          args = thisArg = null;
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Defers executing the `func` function until the current call stack has cleared.
+     * Additional arguments will be provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to defer.
+     * @param {...*} [arg] Arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.defer(function(text) { console.log(text); }, 'deferred');
+     * // logs 'deferred' after one or more milliseconds
+     */
+    function defer(func) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var args = slice(arguments, 1);
+      return setTimeout(function() { func.apply(undefined, args); }, 1);
+    }
+
+    /**
+     * Executes the `func` function after `wait` milliseconds. Additional arguments
+     * will be provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to delay.
+     * @param {number} wait The number of milliseconds to delay execution.
+     * @param {...*} [arg] Arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.delay(function(text) { console.log(text); }, 1000, 'later');
+     * // => logs 'later' after one second
+     */
+    function delay(func, wait) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var args = slice(arguments, 2);
+      return setTimeout(function() { func.apply(undefined, args); }, wait);
+    }
+
+    /**
+     * Creates a function that memoizes the result of `func`. If `resolver` is
+     * provided it will be used to determine the cache key for storing the result
+     * based on the arguments provided to the memoized function. By default, the
+     * first argument provided to the memoized function is used as the cache key.
+     * The `func` is executed with the `this` binding of the memoized function.
+     * The result cache is exposed as the `cache` property on the memoized function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to have its output memoized.
+     * @param {Function} [resolver] A function used to resolve the cache key.
+     * @returns {Function} Returns the new memoizing function.
+     * @example
+     *
+     * var fibonacci = _.memoize(function(n) {
+     *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+     * });
+     *
+     * fibonacci(9)
+     * // => 34
+     *
+     * var data = {
+     *   'fred': { 'name': 'fred', 'age': 40 },
+     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // modifying the result cache
+     * var get = _.memoize(function(name) { return data[name]; }, _.identity);
+     * get('pebbles');
+     * // => { 'name': 'pebbles', 'age': 1 }
+     *
+     * get.cache.pebbles.name = 'penelope';
+     * get('pebbles');
+     * // => { 'name': 'penelope', 'age': 1 }
+     */
+    function memoize(func, resolver) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var memoized = function() {
+        var cache = memoized.cache,
+            key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
+
+        return hasOwnProperty.call(cache, key)
+          ? cache[key]
+          : (cache[key] = func.apply(this, arguments));
+      }
+      memoized.cache = {};
+      return memoized;
+    }
+
+    /**
+     * Creates a function that is restricted to execute `func` once. Repeat calls to
+     * the function will return the value of the first call. The `func` is executed
+     * with the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var initialize = _.once(createApplication);
+     * initialize();
+     * initialize();
+     * // `initialize` executes `createApplication` once
+     */
+    function once(func) {
+      var ran,
+          result;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      return function() {
+        if (ran) {
+          return result;
+        }
+        ran = true;
+        result = func.apply(this, arguments);
+
+        // clear the `func` variable so the function may be garbage collected
+        func = null;
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that, when called, invokes `func` with any additional
+     * `partial` arguments prepended to those provided to the new function. This
+     * method is similar to `_.bind` except it does **not** alter the `this` binding.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var greet = function(greeting, name) { return greeting + ' ' + name; };
+     * var hi = _.partial(greet, 'hi');
+     * hi('fred');
+     * // => 'hi fred'
+     */
+    function partial(func) {
+      return createWrapper(func, 16, slice(arguments, 1));
+    }
+
+    /**
+     * This method is like `_.partial` except that `partial` arguments are
+     * appended to those provided to the new function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var defaultsDeep = _.partialRight(_.merge, _.defaults);
+     *
+     * var options = {
+     *   'variable': 'data',
+     *   'imports': { 'jq': $ }
+     * };
+     *
+     * defaultsDeep(options, _.templateSettings);
+     *
+     * options.variable
+     * // => 'data'
+     *
+     * options.imports
+     * // => { '_': _, 'jq': $ }
+     */
+    function partialRight(func) {
+      return createWrapper(func, 32, null, slice(arguments, 1));
+    }
+
+    /**
+     * Creates a function that, when executed, will only call the `func` function
+     * at most once per every `wait` milliseconds. Provide an options object to
+     * indicate that `func` should be invoked on the leading and/or trailing edge
+     * of the `wait` timeout. Subsequent calls to the throttled function will
+     * return the result of the last `func` call.
+     *
+     * Note: If `leading` and `trailing` options are `true` `func` will be called
+     * on the trailing edge of the timeout only if the the throttled function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to throttle.
+     * @param {number} wait The number of milliseconds to throttle executions to.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
+     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+     * @returns {Function} Returns the new throttled function.
+     * @example
+     *
+     * // avoid excessively updating the position while scrolling
+     * var throttled = _.throttle(updatePosition, 100);
+     * jQuery(window).on('scroll', throttled);
+     *
+     * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
+     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+     *   'trailing': false
+     * }));
+     */
+    function throttle(func, wait, options) {
+      var leading = true,
+          trailing = true;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      if (options === false) {
+        leading = false;
+      } else if (isObject(options)) {
+        leading = 'leading' in options ? options.leading : leading;
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+      debounceOptions.leading = leading;
+      debounceOptions.maxWait = wait;
+      debounceOptions.trailing = trailing;
+
+      return debounce(func, wait, debounceOptions);
+    }
+
+    /**
+     * Creates a function that provides `value` to the wrapper function as its
+     * first argument. Additional arguments provided to the function are appended
+     * to those provided to the wrapper function. The wrapper is executed with
+     * the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {*} value The value to wrap.
+     * @param {Function} wrapper The wrapper function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var p = _.wrap(_.escape, function(func, text) {
+     *   return '<p>' + func(text) + '</p>';
+     * });
+     *
+     * p('Fred, Wilma, & Pebbles');
+     * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
+     */
+    function wrap(value, wrapper) {
+      return createWrapper(wrapper, 16, [value]);
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a function that returns `value`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} value The value to return from the new function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * var getter = _.constant(object);
+     * getter() === object;
+     * // => true
+     */
+    function constant(value) {
+      return function() {
+        return value;
+      };
+    }
+
+    /**
+     * Produces a callback bound to an optional `thisArg`. If `func` is a property
+     * name the created callback will return the property value for a given element.
+     * If `func` is an object the created callback will return `true` for elements
+     * that contain the equivalent object properties, otherwise it will return `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} [func=identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of the created callback.
+     * @param {number} [argCount] The number of arguments the callback accepts.
+     * @returns {Function} Returns a callback function.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // wrap to create custom callback shorthands
+     * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
+     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
+     *   return !match ? func(callback, thisArg) : function(object) {
+     *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
+     *   };
+     * });
+     *
+     * _.filter(characters, 'age__gt38');
+     * // => [{ 'name': 'fred', 'age': 40 }]
+     */
+    function createCallback(func, thisArg, argCount) {
+      var type = typeof func;
+      if (func == null || type == 'function') {
+        return baseCreateCallback(func, thisArg, argCount);
+      }
+      // handle "_.pluck" style callback shorthands
+      if (type != 'object') {
+        return property(func);
+      }
+      var props = keys(func),
+          key = props[0],
+          a = func[key];
+
+      // handle "_.where" style callback shorthands
+      if (props.length == 1 && a === a && !isObject(a)) {
+        // fast path the common case of providing an object with a single
+        // property containing a primitive value
+        return function(object) {
+          var b = object[key];
+          return a === b && (a !== 0 || (1 / a == 1 / b));
+        };
+      }
+      return function(object) {
+        var length = props.length,
+            result = false;
+
+        while (length--) {
+          if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+     * corresponding HTML entities.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} string The string to escape.
+     * @returns {string} Returns the escaped string.
+     * @example
+     *
+     * _.escape('Fred, Wilma, & Pebbles');
+     * // => 'Fred, Wilma, &amp; Pebbles'
+     */
+    function escape(string) {
+      return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
+    }
+
+    /**
+     * This method returns the first argument provided to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} value Any value.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * _.identity(object) === object;
+     * // => true
+     */
+    function identity(value) {
+      return value;
+    }
+
+    /**
+     * Adds function properties of a source object to the destination object.
+     * If `object` is a function methods will be added to its prototype as well.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {Function|Object} [object=lodash] object The destination object.
+     * @param {Object} source The object of functions to add.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
+     * @example
+     *
+     * function capitalize(string) {
+     *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+     * }
+     *
+     * _.mixin({ 'capitalize': capitalize });
+     * _.capitalize('fred');
+     * // => 'Fred'
+     *
+     * _('fred').capitalize().value();
+     * // => 'Fred'
+     *
+     * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
+     * _('fred').capitalize();
+     * // => 'Fred'
+     */
+    function mixin(object, source, options) {
+      var chain = true,
+          methodNames = source && functions(source);
+
+      if (!source || (!options && !methodNames.length)) {
+        if (options == null) {
+          options = source;
+        }
+        ctor = lodashWrapper;
+        source = object;
+        object = lodash;
+        methodNames = functions(source);
+      }
+      if (options === false) {
+        chain = false;
+      } else if (isObject(options) && 'chain' in options) {
+        chain = options.chain;
+      }
+      var ctor = object,
+          isFunc = isFunction(ctor);
+
+      forEach(methodNames, function(methodName) {
+        var func = object[methodName] = source[methodName];
+        if (isFunc) {
+          ctor.prototype[methodName] = function() {
+            var chainAll = this.__chain__,
+                value = this.__wrapped__,
+                args = [value];
+
+            push.apply(args, arguments);
+            var result = func.apply(object, args);
+            if (chain || chainAll) {
+              if (value === result && isObject(result)) {
+                return this;
+              }
+              result = new ctor(result);
+              result.__chain__ = chainAll;
+            }
+            return result;
+          };
+        }
+      });
+    }
+
+    /**
+     * Reverts the '_' variable to its previous value and returns a reference to
+     * the `lodash` function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @returns {Function} Returns the `lodash` function.
+     * @example
+     *
+     * var lodash = _.noConflict();
+     */
+    function noConflict() {
+      context._ = oldDash;
+      return this;
+    }
+
+    /**
+     * A no-operation function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * _.noop(object) === undefined;
+     * // => true
+     */
+    function noop() {
+      // no operation performed
+    }
+
+    /**
+     * Gets the number of milliseconds that have elapsed since the Unix epoch
+     * (1 January 1970 00:00:00 UTC).
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @example
+     *
+     * var stamp = _.now();
+     * _.defer(function() { console.log(_.now() - stamp); });
+     * // => logs the number of milliseconds it took for the deferred function to be called
+     */
+    var now = isNative(now = Date.now) && now || function() {
+      return new Date().getTime();
+    };
+
+    /**
+     * Converts the given value into an integer of the specified radix.
+     * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
+     * `value` is a hexadecimal, in which case a `radix` of `16` is used.
+     *
+     * Note: This method avoids differences in native ES3 and ES5 `parseInt`
+     * implementations. See http://es5.github.io/#E.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} value The value to parse.
+     * @param {number} [radix] The radix used to interpret the value to parse.
+     * @returns {number} Returns the new integer value.
+     * @example
+     *
+     * _.parseInt('08');
+     * // => 8
+     */
+    var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
+      // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
+      return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
+    };
+
+    /**
+     * Creates a "_.pluck" style function, which returns the `key` value of a
+     * given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} key The name of the property to retrieve.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'fred',   'age': 40 },
+     *   { 'name': 'barney', 'age': 36 }
+     * ];
+     *
+     * var getName = _.property('name');
+     *
+     * _.map(characters, getName);
+     * // => ['barney', 'fred']
+     *
+     * _.sortBy(characters, getName);
+     * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
+     */
+    function property(key) {
+      return function(object) {
+        return object[key];
+      };
+    }
+
+    /**
+     * Produces a random number between `min` and `max` (inclusive). If only one
+     * argument is provided a number between `0` and the given number will be
+     * returned. If `floating` is truey or either `min` or `max` are floats a
+     * floating-point number will be returned instead of an integer.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {number} [min=0] The minimum possible value.
+     * @param {number} [max=1] The maximum possible value.
+     * @param {boolean} [floating=false] Specify returning a floating-point number.
+     * @returns {number} Returns a random number.
+     * @example
+     *
+     * _.random(0, 5);
+     * // => an integer between 0 and 5
+     *
+     * _.random(5);
+     * // => also an integer between 0 and 5
+     *
+     * _.random(5, true);
+     * // => a floating-point number between 0 and 5
+     *
+     * _.random(1.2, 5.2);
+     * // => a floating-point number between 1.2 and 5.2
+     */
+    function random(min, max, floating) {
+      var noMin = min == null,
+          noMax = max == null;
+
+      if (floating == null) {
+        if (typeof min == 'boolean' && noMax) {
+          floating = min;
+          min = 1;
+        }
+        else if (!noMax && typeof max == 'boolean') {
+          floating = max;
+          noMax = true;
+        }
+      }
+      if (noMin && noMax) {
+        max = 1;
+      }
+      min = +min || 0;
+      if (noMax) {
+        max = min;
+        min = 0;
+      } else {
+        max = +max || 0;
+      }
+      if (floating || min % 1 || max % 1) {
+        var rand = nativeRandom();
+        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
+      }
+      return baseRandom(min, max);
+    }
+
+    /**
+     * Resolves the value of property `key` on `object`. If `key` is a function
+     * it will be invoked with the `this` binding of `object` and its result returned,
+     * else the property value is returned. If `object` is falsey then `undefined`
+     * is returned.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {Object} object The object to inspect.
+     * @param {string} key The name of the property to resolve.
+     * @returns {*} Returns the resolved value.
+     * @example
+     *
+     * var object = {
+     *   'cheese': 'crumpets',
+     *   'stuff': function() {
+     *     return 'nonsense';
+     *   }
+     * };
+     *
+     * _.result(object, 'cheese');
+     * // => 'crumpets'
+     *
+     * _.result(object, 'stuff');
+     * // => 'nonsense'
+     */
+    function result(object, key) {
+      if (object) {
+        var value = object[key];
+        return isFunction(value) ? object[key]() : value;
+      }
+    }
+
+    /**
+     * A micro-templating method that handles arbitrary delimiters, preserves
+     * whitespace, and correctly escapes quotes within interpolated code.
+     *
+     * Note: In the development build, `_.template` utilizes sourceURLs for easier
+     * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+     *
+     * For more information on precompiling templates see:
+     * http://lodash.com/custom-builds
+     *
+     * For more information on Chrome extension sandboxes see:
+     * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} text The template text.
+     * @param {Object} data The data object used to populate the text.
+     * @param {Object} [options] The options object.
+     * @param {RegExp} [options.escape] The "escape" delimiter.
+     * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+     * @param {Object} [options.imports] An object to import into the template as local variables.
+     * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+     * @param {string} [sourceURL] The sourceURL of the template's compiled source.
+     * @param {string} [variable] The data object variable name.
+     * @returns {Function|string} Returns a compiled function when no `data` object
+     *  is given, else it returns the interpolated text.
+     * @example
+     *
+     * // using the "interpolate" delimiter to create a compiled template
+     * var compiled = _.template('hello <%= name %>');
+     * compiled({ 'name': 'fred' });
+     * // => 'hello fred'
+     *
+     * // using the "escape" delimiter to escape HTML in data property values
+     * _.template('<b><%- value %></b>', { 'value': '<script>' });
+     * // => '<b>&lt;script&gt;</b>'
+     *
+     * // using the "evaluate" delimiter to generate HTML
+     * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
+     * _.template(list, { 'people': ['fred', 'barney'] });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+     * _.template('hello ${ name }', { 'name': 'pebbles' });
+     * // => 'hello pebbles'
+     *
+     * // using the internal `print` function in "evaluate" delimiters
+     * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
+     * // => 'hello barney!'
+     *
+     * // using a custom template delimiters
+     * _.templateSettings = {
+     *   'interpolate': /{{([\s\S]+?)}}/g
+     * };
+     *
+     * _.template('hello {{ name }}!', { 'name': 'mustache' });
+     * // => 'hello mustache!'
+     *
+     * // using the `imports` option to import jQuery
+     * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
+     * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the `sourceURL` option to specify a custom sourceURL for the template
+     * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+     * compiled(data);
+     * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+     *
+     * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+     * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+     * compiled.source;
+     * // => function(data) {
+     *   var __t, __p = '', __e = _.escape;
+     *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+     *   return __p;
+     * }
+     *
+     * // using the `source` property to inline compiled templates for meaningful
+     * // line numbers in error messages and a stack trace
+     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+     *   var JST = {\
+     *     "main": ' + _.template(mainText).source + '\
+     *   };\
+     * ');
+     */
+    function template(text, data, options) {
+      // based on John Resig's `tmpl` implementation
+      // http://ejohn.org/blog/javascript-micro-templating/
+      // and Laura Doktorova's doT.js
+      // https://github.com/olado/doT
+      var settings = lodash.templateSettings;
+      text = String(text || '');
+
+      // avoid missing dependencies when `iteratorTemplate` is not defined
+      options = defaults({}, options, settings);
+
+      var imports = defaults({}, options.imports, settings.imports),
+          importsKeys = keys(imports),
+          importsValues = values(imports);
+
+      var isEvaluating,
+          index = 0,
+          interpolate = options.interpolate || reNoMatch,
+          source = "__p += '";
+
+      // compile the regexp to match each delimiter
+      var reDelimiters = RegExp(
+        (options.escape || reNoMatch).source + '|' +
+        interpolate.source + '|' +
+        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+        (options.evaluate || reNoMatch).source + '|$'
+      , 'g');
+
+      text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+        interpolateValue || (interpolateValue = esTemplateValue);
+
+        // escape characters that cannot be included in string literals
+        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+        // replace delimiters with snippets
+        if (escapeValue) {
+          source += "' +\n__e(" + escapeValue + ") +\n'";
+        }
+        if (evaluateValue) {
+          isEvaluating = true;
+          source += "';\n" + evaluateValue + ";\n__p += '";
+        }
+        if (interpolateValue) {
+          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+        }
+        index = offset + match.length;
+
+        // the JS engine embedded in Adobe products requires returning the `match`
+        // string in order to produce the correct `offset` value
+        return match;
+      });
+
+      source += "';\n";
+
+      // if `variable` is not specified, wrap a with-statement around the generated
+      // code to add the data object to the top of the scope chain
+      var variable = options.variable,
+          hasVariable = variable;
+
+      if (!hasVariable) {
+        variable = 'obj';
+        source = 'with (' + variable + ') {\n' + source + '\n}\n';
+      }
+      // cleanup code by stripping empty strings
+      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+        .replace(reEmptyStringMiddle, '$1')
+        .replace(reEmptyStringTrailing, '$1;');
+
+      // frame code as the function body
+      source = 'function(' + variable + ') {\n' +
+        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+        "var __t, __p = '', __e = _.escape" +
+        (isEvaluating
+          ? ', __j = Array.prototype.join;\n' +
+            "function print() { __p += __j.call(arguments, '') }\n"
+          : ';\n'
+        ) +
+        source +
+        'return __p\n}';
+
+      // Use a sourceURL for easier debugging.
+      // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+      var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
+
+      try {
+        var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
+      } catch(e) {
+        e.source = source;
+        throw e;
+      }
+      if (data) {
+        return result(data);
+      }
+      // provide the compiled function's source by its `toString` method, in
+      // supported environments, or the `source` property as a convenience for
+      // inlining compiled templates during the build process
+      result.source = source;
+      return result;
+    }
+
+    /**
+     * Executes the callback `n` times, returning an array of the results
+     * of each callback execution. The callback is bound to `thisArg` and invoked
+     * with one argument; (index).
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {number} n The number of times to execute the callback.
+     * @param {Function} callback The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns an array of the results of each `callback` execution.
+     * @example
+     *
+     * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+     * // => [3, 6, 4]
+     *
+     * _.times(3, function(n) { mage.castSpell(n); });
+     * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+     *
+     * _.times(3, function(n) { this.cast(n); }, mage);
+     * // => also calls `mage.castSpell(n)` three times
+     */
+    function times(n, callback, thisArg) {
+      n = (n = +n) > -1 ? n : 0;
+      var index = -1,
+          result = Array(n);
+
+      callback = baseCreateCallback(callback, thisArg, 1);
+      while (++index < n) {
+        result[index] = callback(index);
+      }
+      return result;
+    }
+
+    /**
+     * The inverse of `_.escape` this method converts the HTML entities
+     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+     * corresponding characters.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} string The string to unescape.
+     * @returns {string} Returns the unescaped string.
+     * @example
+     *
+     * _.unescape('Fred, Barney &amp; Pebbles');
+     * // => 'Fred, Barney & Pebbles'
+     */
+    function unescape(string) {
+      return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
+    }
+
+    /**
+     * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} [prefix] The value to prefix the ID with.
+     * @returns {string} Returns the unique ID.
+     * @example
+     *
+     * _.uniqueId('contact_');
+     * // => 'contact_104'
+     *
+     * _.uniqueId();
+     * // => '105'
+     */
+    function uniqueId(prefix) {
+      var id = ++idCounter;
+      return String(prefix == null ? '' : prefix) + id;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object that wraps the given value with explicit
+     * method chaining enabled.
+     *
+     * @static
+     * @memberOf _
+     * @category Chaining
+     * @param {*} value The value to wrap.
+     * @returns {Object} Returns the wrapper object.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36 },
+     *   { 'name': 'fred',    'age': 40 },
+     *   { 'name': 'pebbles', 'age': 1 }
+     * ];
+     *
+     * var youngest = _.chain(characters)
+     *     .sortBy('age')
+     *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
+     *     .first()
+     *     .value();
+     * // => 'pebbles is 1'
+     */
+    function chain(value) {
+      value = new lodashWrapper(value);
+      value.__chain__ = true;
+      return value;
+    }
+
+    /**
+     * Invokes `interceptor` with the `value` as the first argument and then
+     * returns `value`. The purpose of this method is to "tap into" a method
+     * chain in order to perform operations on intermediate results within
+     * the chain.
+     *
+     * @static
+     * @memberOf _
+     * @category Chaining
+     * @param {*} value The value to provide to `interceptor`.
+     * @param {Function} interceptor The function to invoke.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * _([1, 2, 3, 4])
+     *  .tap(function(array) { array.pop(); })
+     *  .reverse()
+     *  .value();
+     * // => [3, 2, 1]
+     */
+    function tap(value, interceptor) {
+      interceptor(value);
+      return value;
+    }
+
+    /**
+     * Enables explicit method chaining on the wrapper object.
+     *
+     * @name chain
+     * @memberOf _
+     * @category Chaining
+     * @returns {*} Returns the wrapper object.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // without explicit chaining
+     * _(characters).first();
+     * // => { 'name': 'barney', 'age': 36 }
+     *
+     * // with explicit chaining
+     * _(characters).chain()
+     *   .first()
+     *   .pick('age')
+     *   .value();
+     * // => { 'age': 36 }
+     */
+    function wrapperChain() {
+      this.__chain__ = true;
+      return this;
+    }
+
+    /**
+     * Produces the `toString` result of the wrapped value.
+     *
+     * @name toString
+     * @memberOf _
+     * @category Chaining
+     * @returns {string} Returns the string result.
+     * @example
+     *
+     * _([1, 2, 3]).toString();
+     * // => '1,2,3'
+     */
+    function wrapperToString() {
+      return String(this.__wrapped__);
+    }
+
+    /**
+     * Extracts the wrapped value.
+     *
+     * @name valueOf
+     * @memberOf _
+     * @alias value
+     * @category Chaining
+     * @returns {*} Returns the wrapped value.
+     * @example
+     *
+     * _([1, 2, 3]).valueOf();
+     * // => [1, 2, 3]
+     */
+    function wrapperValueOf() {
+      return this.__wrapped__;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions that return wrapped values when chaining
+    lodash.after = after;
+    lodash.assign = assign;
+    lodash.at = at;
+    lodash.bind = bind;
+    lodash.bindAll = bindAll;
+    lodash.bindKey = bindKey;
+    lodash.chain = chain;
+    lodash.compact = compact;
+    lodash.compose = compose;
+    lodash.constant = constant;
+    lodash.countBy = countBy;
+    lodash.create = create;
+    lodash.createCallback = createCallback;
+    lodash.curry = curry;
+    lodash.debounce = debounce;
+    lodash.defaults = defaults;
+    lodash.defer = defer;
+    lodash.delay = delay;
+    lodash.difference = difference;
+    lodash.filter = filter;
+    lodash.flatten = flatten;
+    lodash.forEach = forEach;
+    lodash.forEachRight = forEachRight;
+    lodash.forIn = forIn;
+    lodash.forInRight = forInRight;
+    lodash.forOwn = forOwn;
+    lodash.forOwnRight = forOwnRight;
+    lodash.functions = functions;
+    lodash.groupBy = groupBy;
+    lodash.indexBy = indexBy;
+    lodash.initial = initial;
+    lodash.intersection = intersection;
+    lodash.invert = invert;
+    lodash.invoke = invoke;
+    lodash.keys = keys;
+    lodash.map = map;
+    lodash.mapValues = mapValues;
+    lodash.max = max;
+    lodash.memoize = memoize;
+    lodash.merge = merge;
+    lodash.min = min;
+    lodash.omit = omit;
+    lodash.once = once;
+    lodash.pairs = pairs;
+    lodash.partial = partial;
+    lodash.partialRight = partialRight;
+    lodash.pick = pick;
+    lodash.pluck = pluck;
+    lodash.property = property;
+    lodash.pull = pull;
+    lodash.range = range;
+    lodash.reject = reject;
+    lodash.remove = remove;
+    lodash.rest = rest;
+    lodash.shuffle = shuffle;
+    lodash.sortBy = sortBy;
+    lodash.tap = tap;
+    lodash.throttle = throttle;
+    lodash.times = times;
+    lodash.toArray = toArray;
+    lodash.transform = transform;
+    lodash.union = union;
+    lodash.uniq = uniq;
+    lodash.values = values;
+    lodash.where = where;
+    lodash.without = without;
+    lodash.wrap = wrap;
+    lodash.xor = xor;
+    lodash.zip = zip;
+    lodash.zipObject = zipObject;
+
+    // add aliases
+    lodash.collect = map;
+    lodash.drop = rest;
+    lodash.each = forEach;
+    lodash.eachRight = forEachRight;
+    lodash.extend = assign;
+    lodash.methods = functions;
+    lodash.object = zipObject;
+    lodash.select = filter;
+    lodash.tail = rest;
+    lodash.unique = uniq;
+    lodash.unzip = zip;
+
+    // add functions to `lodash.prototype`
+    mixin(lodash);
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions that return unwrapped values when chaining
+    lodash.clone = clone;
+    lodash.cloneDeep = cloneDeep;
+    lodash.contains = contains;
+    lodash.escape = escape;
+    lodash.every = every;
+    lodash.find = find;
+    lodash.findIndex = findIndex;
+    lodash.findKey = findKey;
+    lodash.findLast = findLast;
+    lodash.findLastIndex = findLastIndex;
+    lodash.findLastKey = findLastKey;
+    lodash.has = has;
+    lodash.identity = identity;
+    lodash.indexOf = indexOf;
+    lodash.isArguments = isArguments;
+    lodash.isArray = isArray;
+    lodash.isBoolean = isBoolean;
+    lodash.isDate = isDate;
+    lodash.isElement = isElement;
+    lodash.isEmpty = isEmpty;
+    lodash.isEqual = isEqual;
+    lodash.isFinite = isFinite;
+    lodash.isFunction = isFunction;
+    lodash.isNaN = isNaN;
+    lodash.isNull = isNull;
+    lodash.isNumber = isNumber;
+    lodash.isObject = isObject;
+    lodash.isPlainObject = isPlainObject;
+    lodash.isRegExp = isRegExp;
+    lodash.isString = isString;
+    lodash.isUndefined = isUndefined;
+    lodash.lastIndexOf = lastIndexOf;
+    lodash.mixin = mixin;
+    lodash.noConflict = noConflict;
+    lodash.noop = noop;
+    lodash.now = now;
+    lodash.parseInt = parseInt;
+    lodash.random = random;
+    lodash.reduce = reduce;
+    lodash.reduceRight = reduceRight;
+    lodash.result = result;
+    lodash.runInContext = runInContext;
+    lodash.size = size;
+    lodash.some = some;
+    lodash.sortedIndex = sortedIndex;
+    lodash.template = template;
+    lodash.unescape = unescape;
+    lodash.uniqueId = uniqueId;
+
+    // add aliases
+    lodash.all = every;
+    lodash.any = some;
+    lodash.detect = find;
+    lodash.findWhere = find;
+    lodash.foldl = reduce;
+    lodash.foldr = reduceRight;
+    lodash.include = contains;
+    lodash.inject = reduce;
+
+    mixin(function() {
+      var source = {}
+      forOwn(lodash, function(func, methodName) {
+        if (!lodash.prototype[methodName]) {
+          source[methodName] = func;
+        }
+      });
+      return source;
+    }(), false);
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions capable of returning wrapped and unwrapped values when chaining
+    lodash.first = first;
+    lodash.last = last;
+    lodash.sample = sample;
+
+    // add aliases
+    lodash.take = first;
+    lodash.head = first;
+
+    forOwn(lodash, function(func, methodName) {
+      var callbackable = methodName !== 'sample';
+      if (!lodash.prototype[methodName]) {
+        lodash.prototype[methodName]= function(n, guard) {
+          var chainAll = this.__chain__,
+              result = func(this.__wrapped__, n, guard);
+
+          return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
+            ? result
+            : new lodashWrapper(result, chainAll);
+        };
+      }
+    });
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The semantic version number.
+     *
+     * @static
+     * @memberOf _
+     * @type string
+     */
+    lodash.VERSION = '2.4.1';
+
+    // add "Chaining" functions to the wrapper
+    lodash.prototype.chain = wrapperChain;
+    lodash.prototype.toString = wrapperToString;
+    lodash.prototype.value = wrapperValueOf;
+    lodash.prototype.valueOf = wrapperValueOf;
+
+    // add `Array` functions that return unwrapped values
+    baseEach(['join', 'pop', 'shift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        var chainAll = this.__chain__,
+            result = func.apply(this.__wrapped__, arguments);
+
+        return chainAll
+          ? new lodashWrapper(result, chainAll)
+          : result;
+      };
+    });
+
+    // add `Array` functions that return the existing wrapped value
+    baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        func.apply(this.__wrapped__, arguments);
+        return this;
+      };
+    });
+
+    // add `Array` functions that return new wrapped values
+    baseEach(['concat', 'slice', 'splice'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
+      };
+    });
+
+    // avoid array-like object bugs with `Array#shift` and `Array#splice`
+    // in IE < 9, Firefox < 10, Narwhal, and RingoJS
+    if (!support.spliceObjects) {
+      baseEach(['pop', 'shift', 'splice'], function(methodName) {
+        var func = arrayRef[methodName],
+            isSplice = methodName == 'splice';
+
+        lodash.prototype[methodName] = function() {
+          var chainAll = this.__chain__,
+              value = this.__wrapped__,
+              result = func.apply(value, arguments);
+
+          if (value.length === 0) {
+            delete value[0];
+          }
+          return (chainAll || isSplice)
+            ? new lodashWrapper(result, chainAll)
+            : result;
+        };
+      });
+    }
+
+    return lodash;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Lo-Dash
+  var _ = runInContext();
+
+  // some AMD build optimizers like r.js check for condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash is loaded with a RequireJS shim config.
+    // See http://requirejs.org/docs/api.html#config-shim
+    root._ = _;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return _;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports && freeModule) {
+    // in Node.js or RingoJS
+    if (moduleExports) {
+      (freeModule.exports = _)._ = _;
+    }
+    // in Narwhal or Rhino -require
+    else {
+      freeExports._ = _;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    root._ = _;
+  }
+}.call(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.compat.min.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.compat.min.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.compat.min.js	(revision 533)
@@ -0,0 +1,61 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
+ * Build: `lodash -o ./dist/lodash.compat.js`
+ */
+;(function(){function n(n,t,e){e=(e||0)-1;for(var r=n?n.length:0;++e<r;)if(n[e]===t)return e;return-1}function t(t,e){var r=typeof e;if(t=t.l,"boolean"==r||null==e)return t[e]?0:-1;"number"!=r&&"string"!=r&&(r="object");var u="number"==r?e:b+e;return t=(t=t[r])&&t[u],"object"==r?t&&-1<n(t,e)?0:-1:t?0:-1}function e(n){var t=this.l,e=typeof n;if("boolean"==e||null==n)t[n]=true;else{"number"!=e&&"string"!=e&&(e="object");var r="number"==e?n:b+n,t=t[e]||(t[e]={});"object"==e?(t[r]||(t[r]=[])).push(n):t[r]=true
+}}function r(n){return n.charCodeAt(0)}function u(n,t){for(var e=n.m,r=t.m,u=-1,o=e.length;++u<o;){var a=e[u],i=r[u];if(a!==i){if(a>i||typeof a=="undefined")return 1;if(a<i||typeof i=="undefined")return-1}}return n.n-t.n}function o(n){var t=-1,r=n.length,u=n[0],o=n[r/2|0],a=n[r-1];if(u&&typeof u=="object"&&o&&typeof o=="object"&&a&&typeof a=="object")return false;for(u=l(),u["false"]=u["null"]=u["true"]=u.undefined=false,o=l(),o.k=n,o.l=u,o.push=e;++t<r;)o.push(n[t]);return o}function a(n){return"\\"+Y[n]
+}function i(){return v.pop()||[]}function l(){return y.pop()||{k:null,l:null,m:null,"false":false,n:0,"null":false,number:null,object:null,push:null,string:null,"true":false,undefined:false,o:null}}function f(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function c(n){n.length=0,v.length<w&&v.push(n)}function p(n){var t=n.l;t&&p(t),n.k=n.l=n.m=n.object=n.number=n.string=n.o=null,y.length<w&&y.push(n)}function s(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);var r=-1;e=e-t||0;for(var u=Array(0>e?0:e);++r<e;)u[r]=n[t+r];
+return u}function g(e){function v(n){return n&&typeof n=="object"&&!qe(n)&&we.call(n,"__wrapped__")?n:new y(n)}function y(n,t){this.__chain__=!!t,this.__wrapped__=n}function w(n){function t(){if(r){var n=s(r);je.apply(n,arguments)}if(this instanceof t){var o=nt(e.prototype),n=e.apply(o,n||arguments);return xt(n)?n:o}return e.apply(u,n||arguments)}var e=n[0],r=n[2],u=n[4];return ze(t,n),t}function Y(n,t,e,r,u){if(e){var o=e(n);if(typeof o!="undefined")return o}if(!xt(n))return n;var a=he.call(n);if(!V[a]||!Le.nodeClass&&f(n))return n;
+var l=Te[a];switch(a){case L:case z:return new l(+n);case W:case M:return new l(n);case J:return o=l(n.source,S.exec(n)),o.lastIndex=n.lastIndex,o}if(a=qe(n),t){var p=!r;r||(r=i()),u||(u=i());for(var g=r.length;g--;)if(r[g]==n)return u[g];o=a?l(n.length):{}}else o=a?s(n):Ye({},n);return a&&(we.call(n,"index")&&(o.index=n.index),we.call(n,"input")&&(o.input=n.input)),t?(r.push(n),u.push(o),(a?Xe:tr)(n,function(n,a){o[a]=Y(n,t,e,r,u)}),p&&(c(r),c(u)),o):o}function nt(n){return xt(n)?Se(n):{}}function tt(n,t,e){if(typeof n!="function")return Ht;
+if(typeof t=="undefined"||!("prototype"in n))return n;var r=n.__bindData__;if(typeof r=="undefined"&&(Le.funcNames&&(r=!n.name),r=r||!Le.funcDecomp,!r)){var u=be.call(n);Le.funcNames||(r=!A.test(u)),r||(r=B.test(u),ze(n,r))}if(false===r||true!==r&&1&r[1])return n;switch(e){case 1:return function(e){return n.call(t,e)};case 2:return function(e,r){return n.call(t,e,r)};case 3:return function(e,r,u){return n.call(t,e,r,u)};case 4:return function(e,r,u,o){return n.call(t,e,r,u,o)}}return Mt(n,t)}function et(n){function t(){var n=l?a:this;
+if(u){var h=s(u);je.apply(h,arguments)}return(o||c)&&(h||(h=s(arguments)),o&&je.apply(h,o),c&&h.length<i)?(r|=16,et([e,p?r:-4&r,h,null,a,i])):(h||(h=arguments),f&&(e=n[g]),this instanceof t?(n=nt(e.prototype),h=e.apply(n,h),xt(h)?h:n):e.apply(n,h))}var e=n[0],r=n[1],u=n[2],o=n[3],a=n[4],i=n[5],l=1&r,f=2&r,c=4&r,p=8&r,g=e;return ze(t,n),t}function rt(e,r){var u=-1,a=ht(),i=e?e.length:0,l=i>=_&&a===n,f=[];if(l){var c=o(r);c?(a=t,r=c):l=false}for(;++u<i;)c=e[u],0>a(r,c)&&f.push(c);return l&&p(r),f}function ot(n,t,e,r){r=(r||0)-1;
+for(var u=n?n.length:0,o=[];++r<u;){var a=n[r];if(a&&typeof a=="object"&&typeof a.length=="number"&&(qe(a)||dt(a))){t||(a=ot(a,t,e));var i=-1,l=a.length,f=o.length;for(o.length+=l;++i<l;)o[f++]=a[i]}else e||o.push(a)}return o}function at(n,t,e,r,u,o){if(e){var a=e(n,t);if(typeof a!="undefined")return!!a}if(n===t)return 0!==n||1/n==1/t;if(n===n&&!(n&&X[typeof n]||t&&X[typeof t]))return false;if(null==n||null==t)return n===t;var l=he.call(n),p=he.call(t);if(l==T&&(l=G),p==T&&(p=G),l!=p)return false;switch(l){case L:case z:return+n==+t;
+case W:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case J:case M:return n==ie(t)}if(p=l==$,!p){var s=we.call(n,"__wrapped__"),g=we.call(t,"__wrapped__");if(s||g)return at(s?n.__wrapped__:n,g?t.__wrapped__:t,e,r,u,o);if(l!=G||!Le.nodeClass&&(f(n)||f(t)))return false;if(l=!Le.argsObject&&dt(n)?oe:n.constructor,s=!Le.argsObject&&dt(t)?oe:t.constructor,l!=s&&!(jt(l)&&l instanceof l&&jt(s)&&s instanceof s)&&"constructor"in n&&"constructor"in t)return false}for(l=!u,u||(u=i()),o||(o=i()),s=u.length;s--;)if(u[s]==n)return o[s]==t;
+var h=0,a=true;if(u.push(n),o.push(t),p){if(s=n.length,h=t.length,(a=h==s)||r)for(;h--;)if(p=s,g=t[h],r)for(;p--&&!(a=at(n[p],g,e,r,u,o)););else if(!(a=at(n[h],g,e,r,u,o)))break}else nr(t,function(t,i,l){return we.call(l,i)?(h++,a=we.call(n,i)&&at(n[i],t,e,r,u,o)):void 0}),a&&!r&&nr(n,function(n,t,e){return we.call(e,t)?a=-1<--h:void 0});return u.pop(),o.pop(),l&&(c(u),c(o)),a}function it(n,t,e,r,u){(qe(t)?Dt:tr)(t,function(t,o){var a,i,l=t,f=n[o];if(t&&((i=qe(t))||er(t))){for(l=r.length;l--;)if(a=r[l]==t){f=u[l];
+break}if(!a){var c;e&&(l=e(f,t),c=typeof l!="undefined")&&(f=l),c||(f=i?qe(f)?f:[]:er(f)?f:{}),r.push(t),u.push(f),c||it(f,t,e,r,u)}}else e&&(l=e(f,t),typeof l=="undefined"&&(l=t)),typeof l!="undefined"&&(f=l);n[o]=f})}function lt(n,t){return n+de(Fe()*(t-n+1))}function ft(e,r,u){var a=-1,l=ht(),f=e?e.length:0,s=[],g=!r&&f>=_&&l===n,h=u||g?i():s;for(g&&(h=o(h),l=t);++a<f;){var v=e[a],y=u?u(v,a,e):v;(r?!a||h[h.length-1]!==y:0>l(h,y))&&((u||g)&&h.push(y),s.push(v))}return g?(c(h.k),p(h)):u&&c(h),s}function ct(n){return function(t,e,r){var u={};
+if(e=v.createCallback(e,r,3),qe(t)){r=-1;for(var o=t.length;++r<o;){var a=t[r];n(u,a,e(a,r,t),t)}}else Xe(t,function(t,r,o){n(u,t,e(t,r,o),o)});return u}}function pt(n,t,e,r,u,o){var a=1&t,i=4&t,l=16&t,f=32&t;if(!(2&t||jt(n)))throw new le;l&&!e.length&&(t&=-17,l=e=false),f&&!r.length&&(t&=-33,f=r=false);var c=n&&n.__bindData__;return c&&true!==c?(c=s(c),c[2]&&(c[2]=s(c[2])),c[3]&&(c[3]=s(c[3])),!a||1&c[1]||(c[4]=u),!a&&1&c[1]&&(t|=8),!i||4&c[1]||(c[5]=o),l&&je.apply(c[2]||(c[2]=[]),e),f&&Ee.apply(c[3]||(c[3]=[]),r),c[1]|=t,pt.apply(null,c)):(1==t||17===t?w:et)([n,t,e,r,u,o])
+}function st(){Q.h=F,Q.b=Q.c=Q.g=Q.i="",Q.e="t",Q.j=true;for(var n,t=0;n=arguments[t];t++)for(var e in n)Q[e]=n[e];t=Q.a,Q.d=/^[^,]+/.exec(t)[0],n=ee,t="return function("+t+"){",e=Q;var r="var n,t="+e.d+",E="+e.e+";if(!t)return E;"+e.i+";";e.b?(r+="var u=t.length;n=-1;if("+e.b+"){",Le.unindexedChars&&(r+="if(s(t)){t=t.split('')}"),r+="while(++n<u){"+e.g+";}}else{"):Le.nonEnumArgs&&(r+="var u=t.length;n=-1;if(u&&p(t)){while(++n<u){n+='';"+e.g+";}}else{"),Le.enumPrototypes&&(r+="var G=typeof t=='function';"),Le.enumErrorProps&&(r+="var F=t===k||t instanceof Error;");
+var u=[];if(Le.enumPrototypes&&u.push('!(G&&n=="prototype")'),Le.enumErrorProps&&u.push('!(F&&(n=="message"||n=="name"))'),e.j&&e.f)r+="var C=-1,D=B[typeof t]&&v(t),u=D?D.length:0;while(++C<u){n=D[C];",u.length&&(r+="if("+u.join("&&")+"){"),r+=e.g+";",u.length&&(r+="}"),r+="}";else if(r+="for(n in t){",e.j&&u.push("m.call(t, n)"),u.length&&(r+="if("+u.join("&&")+"){"),r+=e.g+";",u.length&&(r+="}"),r+="}",Le.nonEnumShadows){for(r+="if(t!==A){var i=t.constructor,r=t===(i&&i.prototype),f=t===J?I:t===k?j:L.call(t),x=y[f];",k=0;7>k;k++)r+="n='"+e.h[k]+"';if((!(r&&x[n])&&m.call(t,n))",e.j||(r+="||(!x[n]&&t[n]!==A[n])"),r+="){"+e.g+"}";
+r+="}"}return(e.b||Le.nonEnumArgs)&&(r+="}"),r+=e.c+";return E",n("d,j,k,m,o,p,q,s,v,A,B,y,I,J,L",t+r+"}")(tt,q,ce,we,d,dt,qe,kt,Q.f,pe,X,$e,M,se,he)}function gt(n){return Ve[n]}function ht(){var t=(t=v.indexOf)===zt?n:t;return t}function vt(n){return typeof n=="function"&&ve.test(n)}function yt(n){var t,e;return!n||he.call(n)!=G||(t=n.constructor,jt(t)&&!(t instanceof t))||!Le.argsClass&&dt(n)||!Le.nodeClass&&f(n)?false:Le.ownLast?(nr(n,function(n,t,r){return e=we.call(r,t),false}),false!==e):(nr(n,function(n,t){e=t
+}),typeof e=="undefined"||we.call(n,e))}function mt(n){return He[n]}function dt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&he.call(n)==T||false}function bt(n,t,e){var r=We(n),u=r.length;for(t=tt(t,e,3);u--&&(e=r[u],false!==t(n[e],e,n)););return n}function _t(n){var t=[];return nr(n,function(n,e){jt(n)&&t.push(e)}),t.sort()}function wt(n){for(var t=-1,e=We(n),r=e.length,u={};++t<r;){var o=e[t];u[n[o]]=o}return u}function jt(n){return typeof n=="function"}function xt(n){return!(!n||!X[typeof n])
+}function Ct(n){return typeof n=="number"||n&&typeof n=="object"&&he.call(n)==W||false}function kt(n){return typeof n=="string"||n&&typeof n=="object"&&he.call(n)==M||false}function Et(n){for(var t=-1,e=We(n),r=e.length,u=Zt(r);++t<r;)u[t]=n[e[t]];return u}function Ot(n,t,e){var r=-1,u=ht(),o=n?n.length:0,a=false;return e=(0>e?Be(0,o+e):e)||0,qe(n)?a=-1<u(n,t,e):typeof o=="number"?a=-1<(kt(n)?n.indexOf(t,e):u(n,t,e)):Xe(n,function(n){return++r<e?void 0:!(a=n===t)}),a}function St(n,t,e){var r=true;if(t=v.createCallback(t,e,3),qe(n)){e=-1;
+for(var u=n.length;++e<u&&(r=!!t(n[e],e,n)););}else Xe(n,function(n,e,u){return r=!!t(n,e,u)});return r}function At(n,t,e){var r=[];if(t=v.createCallback(t,e,3),qe(n)){e=-1;for(var u=n.length;++e<u;){var o=n[e];t(o,e,n)&&r.push(o)}}else Xe(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function It(n,t,e){if(t=v.createCallback(t,e,3),!qe(n)){var r;return Xe(n,function(n,e,u){return t(n,e,u)?(r=n,false):void 0}),r}e=-1;for(var u=n.length;++e<u;){var o=n[e];if(t(o,e,n))return o}}function Dt(n,t,e){if(t&&typeof e=="undefined"&&qe(n)){e=-1;
+for(var r=n.length;++e<r&&false!==t(n[e],e,n););}else Xe(n,t,e);return n}function Nt(n,t,e){var r=n,u=n?n.length:0;if(t=t&&typeof e=="undefined"?t:tt(t,e,3),qe(n))for(;u--&&false!==t(n[u],u,n););else{if(typeof u!="number")var o=We(n),u=o.length;else Le.unindexedChars&&kt(n)&&(r=n.split(""));Xe(n,function(n,e,a){return e=o?o[--u]:--u,t(r[e],e,a)})}return n}function Bt(n,t,e){var r=-1,u=n?n.length:0,o=Zt(typeof u=="number"?u:0);if(t=v.createCallback(t,e,3),qe(n))for(;++r<u;)o[r]=t(n[r],r,n);else Xe(n,function(n,e,u){o[++r]=t(n,e,u)
+});return o}function Pt(n,t,e){var u=-1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&qe(n)){e=-1;for(var a=n.length;++e<a;){var i=n[e];i>o&&(o=i)}}else t=null==t&&kt(n)?r:v.createCallback(t,e,3),Xe(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Rt(n,t,e,r){var u=3>arguments.length;if(t=v.createCallback(t,r,4),qe(n)){var o=-1,a=n.length;for(u&&(e=n[++o]);++o<a;)e=t(e,n[o],o,n)}else Xe(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)});return e}function Ft(n,t,e,r){var u=3>arguments.length;
+return t=v.createCallback(t,r,4),Nt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Tt(n){var t=-1,e=n?n.length:0,r=Zt(typeof e=="number"?e:0);return Dt(n,function(n){var e=lt(0,++t);r[t]=r[e],r[e]=n}),r}function $t(n,t,e){var r;if(t=v.createCallback(t,e,3),qe(n)){e=-1;for(var u=n.length;++e<u&&!(r=t(n[e],e,n)););}else Xe(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function Lt(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=-1;for(t=v.createCallback(t,e,3);++o<u&&t(n[o],o,n);)r++
+}else if(r=t,null==r||e)return n?n[0]:h;return s(n,0,Pe(Be(0,r),u))}function zt(t,e,r){if(typeof r=="number"){var u=t?t.length:0;r=0>r?Be(0,u+r):r||0}else if(r)return r=Kt(t,e),t[r]===e?r:-1;return n(t,e,r)}function qt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=v.createCallback(t,e,3);++u<o&&t(n[u],u,n);)r++}else r=null==t||e?1:Be(0,t);return s(n,r)}function Kt(n,t,e,r){var u=0,o=n?n.length:u;for(e=e?v.createCallback(e,r,1):Ht,t=e(t);u<o;)r=u+o>>>1,e(n[r])<t?u=r+1:o=r;
+return u}function Wt(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(e=v.createCallback(e,r,3)),ft(n,t,e)}function Gt(){for(var n=1<arguments.length?arguments:arguments[0],t=-1,e=n?Pt(ar(n,"length")):0,r=Zt(0>e?0:e);++t<e;)r[t]=ar(n,t);return r}function Jt(n,t){var e=-1,r=n?n.length:0,u={};for(t||!r||qe(n[0])||(t=[]);++e<r;){var o=n[e];t?u[o]=t[e]:o&&(u[o[0]]=o[1])}return u}function Mt(n,t){return 2<arguments.length?pt(n,17,s(arguments,2),null,t):pt(n,1,null,null,t)
+}function Vt(n,t,e){var r,u,o,a,i,l,f,c=0,p=false,s=true;if(!jt(n))throw new le;if(t=Be(0,t)||0,true===e)var g=true,s=false;else xt(e)&&(g=e.leading,p="maxWait"in e&&(Be(t,e.maxWait)||0),s="trailing"in e?e.trailing:s);var v=function(){var e=t-(ir()-a);0<e?l=Ce(v,e):(u&&me(u),e=f,u=l=f=h,e&&(c=ir(),o=n.apply(i,r),l||u||(r=i=null)))},y=function(){l&&me(l),u=l=f=h,(s||p!==t)&&(c=ir(),o=n.apply(i,r),l||u||(r=i=null))};return function(){if(r=arguments,a=ir(),i=this,f=s&&(l||!g),false===p)var e=g&&!l;else{u||g||(c=a);
+var h=p-(a-c),m=0>=h;m?(u&&(u=me(u)),c=a,o=n.apply(i,r)):u||(u=Ce(y,h))}return m&&l?l=me(l):l||t===p||(l=Ce(v,t)),e&&(m=true,o=n.apply(i,r)),!m||l||u||(r=i=null),o}}function Ht(n){return n}function Ut(n,t,e){var r=true,u=t&&_t(t);t&&(e||u.length)||(null==e&&(e=t),o=y,t=n,n=v,u=_t(t)),false===e?r=false:xt(e)&&"chain"in e&&(r=e.chain);var o=n,a=jt(o);Dt(u,function(e){var u=n[e]=t[e];a&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,a=[e];if(je.apply(a,arguments),a=u.apply(n,a),r||t){if(e===a&&xt(a))return this;
+a=new o(a),a.__chain__=t}return a})})}function Qt(){}function Xt(n){return function(t){return t[n]}}function Yt(){return this.__wrapped__}e=e?ut.defaults(Z.Object(),e,ut.pick(Z,R)):Z;var Zt=e.Array,ne=e.Boolean,te=e.Date,ee=e.Function,re=e.Math,ue=e.Number,oe=e.Object,ae=e.RegExp,ie=e.String,le=e.TypeError,fe=[],ce=e.Error.prototype,pe=oe.prototype,se=ie.prototype,ge=e._,he=pe.toString,ve=ae("^"+ie(he).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),ye=re.ceil,me=e.clearTimeout,de=re.floor,be=ee.prototype.toString,_e=vt(_e=oe.getPrototypeOf)&&_e,we=pe.hasOwnProperty,je=fe.push,xe=pe.propertyIsEnumerable,Ce=e.setTimeout,ke=fe.splice,Ee=fe.unshift,Oe=function(){try{var n={},t=vt(t=oe.defineProperty)&&t,e=t(n,n,n)&&t
+}catch(r){}return e}(),Se=vt(Se=oe.create)&&Se,Ae=vt(Ae=Zt.isArray)&&Ae,Ie=e.isFinite,De=e.isNaN,Ne=vt(Ne=oe.keys)&&Ne,Be=re.max,Pe=re.min,Re=e.parseInt,Fe=re.random,Te={};Te[$]=Zt,Te[L]=ne,Te[z]=te,Te[K]=ee,Te[G]=oe,Te[W]=ue,Te[J]=ae,Te[M]=ie;var $e={};$e[$]=$e[z]=$e[W]={constructor:true,toLocaleString:true,toString:true,valueOf:true},$e[L]=$e[M]={constructor:true,toString:true,valueOf:true},$e[q]=$e[K]=$e[J]={constructor:true,toString:true},$e[G]={constructor:true},function(){for(var n=F.length;n--;){var t,e=F[n];
+for(t in $e)we.call($e,t)&&!we.call($e[t],e)&&($e[t][e]=false)}}(),y.prototype=v.prototype;var Le=v.support={};!function(){var n=function(){this.x=1},t={0:1,length:1},r=[];n.prototype={valueOf:1,y:1};for(var u in new n)r.push(u);for(u in arguments);Le.argsClass=he.call(arguments)==T,Le.argsObject=arguments.constructor==oe&&!(arguments instanceof Zt),Le.enumErrorProps=xe.call(ce,"message")||xe.call(ce,"name"),Le.enumPrototypes=xe.call(n,"prototype"),Le.funcDecomp=!vt(e.WinRTError)&&B.test(g),Le.funcNames=typeof ee.name=="string",Le.nonEnumArgs=0!=u,Le.nonEnumShadows=!/valueOf/.test(r),Le.ownLast="x"!=r[0],Le.spliceObjects=(fe.splice.call(t,0,1),!t[0]),Le.unindexedChars="xx"!="x"[0]+oe("x")[0];
+try{Le.nodeClass=!(he.call(document)==G&&!({toString:0}+""))}catch(o){Le.nodeClass=true}}(1),v.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:I,variable:"",imports:{_:v}},Se||(nt=function(){function n(){}return function(t){if(xt(t)){n.prototype=t;var r=new n;n.prototype=null}return r||e.Object()}}());var ze=Oe?function(n,t){U.value=t,Oe(n,"__bindData__",U)}:Qt;Le.argsClass||(dt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&we.call(n,"callee")&&!xe.call(n,"callee")||false
+});var qe=Ae||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&he.call(n)==$||false},Ke=st({a:"z",e:"[]",i:"if(!(B[typeof z]))return E",g:"E.push(n)"}),We=Ne?function(n){return xt(n)?Le.enumPrototypes&&typeof n=="function"||Le.nonEnumArgs&&n.length&&dt(n)?Ke(n):Ne(n):[]}:Ke,Ge={a:"g,e,K",i:"e=e&&typeof K=='undefined'?e:d(e,K,3)",b:"typeof u=='number'",v:We,g:"if(e(t[n],n,g)===false)return E"},Je={a:"z,H,l",i:"var a=arguments,b=0,c=typeof l=='number'?2:a.length;while(++b<c){t=a[b];if(t&&B[typeof t]){",v:We,g:"if(typeof E[n]=='undefined')E[n]=t[n]",c:"}}"},Me={i:"if(!B[typeof t])return E;"+Ge.i,b:false},Ve={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},He=wt(Ve),Ue=ae("("+We(He).join("|")+")","g"),Qe=ae("["+We(Ve).join("")+"]","g"),Xe=st(Ge),Ye=st(Je,{i:Je.i.replace(";",";if(c>3&&typeof a[c-2]=='function'){var e=d(a[--c-1],a[c--],2)}else if(c>2&&typeof a[c-1]=='function'){e=a[--c]}"),g:"E[n]=e?e(E[n],t[n]):t[n]"}),Ze=st(Je),nr=st(Ge,Me,{j:false}),tr=st(Ge,Me);
+jt(/x/)&&(jt=function(n){return typeof n=="function"&&he.call(n)==K});var er=_e?function(n){if(!n||he.call(n)!=G||!Le.argsClass&&dt(n))return false;var t=n.valueOf,e=vt(t)&&(e=_e(t))&&_e(e);return e?n==e||_e(n)==e:yt(n)}:yt,rr=ct(function(n,t,e){we.call(n,e)?n[e]++:n[e]=1}),ur=ct(function(n,t,e){(we.call(n,e)?n[e]:n[e]=[]).push(t)}),or=ct(function(n,t,e){n[e]=t}),ar=Bt,ir=vt(ir=te.now)&&ir||function(){return(new te).getTime()},lr=8==Re(j+"08")?Re:function(n,t){return Re(kt(n)?n.replace(D,""):n,t||0)};
+return v.after=function(n,t){if(!jt(t))throw new le;return function(){return 1>--n?t.apply(this,arguments):void 0}},v.assign=Ye,v.at=function(n){var t=arguments,e=-1,r=ot(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=Zt(t);for(Le.unindexedChars&&kt(n)&&(n=n.split(""));++e<t;)u[e]=n[r[e]];return u},v.bind=Mt,v.bindAll=function(n){for(var t=1<arguments.length?ot(arguments,true,false,1):_t(n),e=-1,r=t.length;++e<r;){var u=t[e];n[u]=pt(n[u],1,null,null,n)}return n},v.bindKey=function(n,t){return 2<arguments.length?pt(t,19,s(arguments,2),null,n):pt(t,3,null,null,n)
+},v.chain=function(n){return n=new y(n),n.__chain__=true,n},v.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},v.compose=function(){for(var n=arguments,t=n.length;t--;)if(!jt(n[t]))throw new le;return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];return t[0]}},v.constant=function(n){return function(){return n}},v.countBy=rr,v.create=function(n,t){var e=nt(n);return t?Ye(e,t):e},v.createCallback=function(n,t,e){var r=typeof n;if(null==n||"function"==r)return tt(n,t,e);
+if("object"!=r)return Xt(n);var u=We(n),o=u[0],a=n[o];return 1!=u.length||a!==a||xt(a)?function(t){for(var e=u.length,r=false;e--&&(r=at(t[u[e]],n[u[e]],null,true)););return r}:function(n){return n=n[o],a===n&&(0!==a||1/a==1/n)}},v.curry=function(n,t){return t=typeof t=="number"?t:+t||n.length,pt(n,4,null,null,null,t)},v.debounce=Vt,v.defaults=Ze,v.defer=function(n){if(!jt(n))throw new le;var t=s(arguments,1);return Ce(function(){n.apply(h,t)},1)},v.delay=function(n,t){if(!jt(n))throw new le;var e=s(arguments,2);
+return Ce(function(){n.apply(h,e)},t)},v.difference=function(n){return rt(n,ot(arguments,true,true,1))},v.filter=At,v.flatten=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(n=Bt(n,e,r)),ot(n,t)},v.forEach=Dt,v.forEachRight=Nt,v.forIn=nr,v.forInRight=function(n,t,e){var r=[];nr(n,function(n,t){r.push(t,n)});var u=r.length;for(t=tt(t,e,3);u--&&false!==t(r[u--],r[u],n););return n},v.forOwn=tr,v.forOwnRight=bt,v.functions=_t,v.groupBy=ur,v.indexBy=or,v.initial=function(n,t,e){var r=0,u=n?n.length:0;
+if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return s(n,0,Pe(Be(0,u-r),u))},v.intersection=function(){for(var e=[],r=-1,u=arguments.length,a=i(),l=ht(),f=l===n,s=i();++r<u;){var g=arguments[r];(qe(g)||dt(g))&&(e.push(g),a.push(f&&g.length>=_&&o(r?e[r]:s)))}var f=e[0],h=-1,v=f?f.length:0,y=[];n:for(;++h<v;){var m=a[0],g=f[h];if(0>(m?t(m,g):l(s,g))){for(r=u,(m||s).push(g);--r;)if(m=a[r],0>(m?t(m,g):l(e[r],g)))continue n;y.push(g)
+}}for(;u--;)(m=a[u])&&p(m);return c(a),c(s),y},v.invert=wt,v.invoke=function(n,t){var e=s(arguments,2),r=-1,u=typeof t=="function",o=n?n.length:0,a=Zt(typeof o=="number"?o:0);return Dt(n,function(n){a[++r]=(u?t:n[t]).apply(n,e)}),a},v.keys=We,v.map=Bt,v.mapValues=function(n,t,e){var r={};return t=v.createCallback(t,e,3),tr(n,function(n,e,u){r[e]=t(n,e,u)}),r},v.max=Pt,v.memoize=function(n,t){if(!jt(n))throw new le;var e=function(){var r=e.cache,u=t?t.apply(this,arguments):b+arguments[0];return we.call(r,u)?r[u]:r[u]=n.apply(this,arguments)
+};return e.cache={},e},v.merge=function(n){var t=arguments,e=2;if(!xt(n))return n;if("number"!=typeof t[2]&&(e=t.length),3<e&&"function"==typeof t[e-2])var r=tt(t[--e-1],t[e--],2);else 2<e&&"function"==typeof t[e-1]&&(r=t[--e]);for(var t=s(arguments,1,e),u=-1,o=i(),a=i();++u<e;)it(n,t[u],r,o,a);return c(o),c(a),n},v.min=function(n,t,e){var u=1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&qe(n)){e=-1;for(var a=n.length;++e<a;){var i=n[e];i<o&&(o=i)}}else t=null==t&&kt(n)?r:v.createCallback(t,e,3),Xe(n,function(n,e,r){e=t(n,e,r),e<u&&(u=e,o=n)
+});return o},v.omit=function(n,t,e){var r={};if(typeof t!="function"){var u=[];nr(n,function(n,t){u.push(t)});for(var u=rt(u,ot(arguments,true,false,1)),o=-1,a=u.length;++o<a;){var i=u[o];r[i]=n[i]}}else t=v.createCallback(t,e,3),nr(n,function(n,e,u){t(n,e,u)||(r[e]=n)});return r},v.once=function(n){var t,e;if(!jt(n))throw new le;return function(){return t?e:(t=true,e=n.apply(this,arguments),n=null,e)}},v.pairs=function(n){for(var t=-1,e=We(n),r=e.length,u=Zt(r);++t<r;){var o=e[t];u[t]=[o,n[o]]}return u
+},v.partial=function(n){return pt(n,16,s(arguments,1))},v.partialRight=function(n){return pt(n,32,null,s(arguments,1))},v.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=-1,o=ot(arguments,true,false,1),a=xt(n)?o.length:0;++u<a;){var i=o[u];i in n&&(r[i]=n[i])}else t=v.createCallback(t,e,3),nr(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},v.pluck=ar,v.property=Xt,v.pull=function(n){for(var t=arguments,e=0,r=t.length,u=n?n.length:0;++e<r;)for(var o=-1,a=t[e];++o<u;)n[o]===a&&(ke.call(n,o--,1),u--);
+return n},v.range=function(n,t,e){n=+n||0,e=typeof e=="number"?e:+e||1,null==t&&(t=n,n=0);var r=-1;t=Be(0,ye((t-n)/(e||1)));for(var u=Zt(t);++r<t;)u[r]=n,n+=e;return u},v.reject=function(n,t,e){return t=v.createCallback(t,e,3),At(n,function(n,e,r){return!t(n,e,r)})},v.remove=function(n,t,e){var r=-1,u=n?n.length:0,o=[];for(t=v.createCallback(t,e,3);++r<u;)e=n[r],t(e,r,n)&&(o.push(e),ke.call(n,r--,1),u--);return o},v.rest=qt,v.shuffle=Tt,v.sortBy=function(n,t,e){var r=-1,o=qe(t),a=n?n.length:0,f=Zt(typeof a=="number"?a:0);
+for(o||(t=v.createCallback(t,e,3)),Dt(n,function(n,e,u){var a=f[++r]=l();o?a.m=Bt(t,function(t){return n[t]}):(a.m=i())[0]=t(n,e,u),a.n=r,a.o=n}),a=f.length,f.sort(u);a--;)n=f[a],f[a]=n.o,o||c(n.m),p(n);return f},v.tap=function(n,t){return t(n),n},v.throttle=function(n,t,e){var r=true,u=true;if(!jt(n))throw new le;return false===e?r=false:xt(e)&&(r="leading"in e?e.leading:r,u="trailing"in e?e.trailing:u),H.leading=r,H.maxWait=t,H.trailing=u,Vt(n,t,H)},v.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=Zt(n);
+for(t=tt(t,e,1);++r<n;)u[r]=t(r);return u},v.toArray=function(n){return n&&typeof n.length=="number"?Le.unindexedChars&&kt(n)?n.split(""):s(n):Et(n)},v.transform=function(n,t,e,r){var u=qe(n);if(null==e)if(u)e=[];else{var o=n&&n.constructor;e=nt(o&&o.prototype)}return t&&(t=v.createCallback(t,r,4),(u?Xe:tr)(n,function(n,r,u){return t(e,n,r,u)})),e},v.union=function(){return ft(ot(arguments,true,true))},v.uniq=Wt,v.values=Et,v.where=At,v.without=function(n){return rt(n,s(arguments,1))},v.wrap=function(n,t){return pt(t,16,[n])
+},v.xor=function(){for(var n=-1,t=arguments.length;++n<t;){var e=arguments[n];if(qe(e)||dt(e))var r=r?ft(rt(r,e).concat(rt(e,r))):e}return r||[]},v.zip=Gt,v.zipObject=Jt,v.collect=Bt,v.drop=qt,v.each=Dt,v.eachRight=Nt,v.extend=Ye,v.methods=_t,v.object=Jt,v.select=At,v.tail=qt,v.unique=Wt,v.unzip=Gt,Ut(v),v.clone=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=t,t=false),Y(n,t,typeof e=="function"&&tt(e,r,1))},v.cloneDeep=function(n,t,e){return Y(n,true,typeof t=="function"&&tt(t,e,1))},v.contains=Ot,v.escape=function(n){return null==n?"":ie(n).replace(Qe,gt)
+},v.every=St,v.find=It,v.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;for(t=v.createCallback(t,e,3);++r<u;)if(t(n[r],r,n))return r;return-1},v.findKey=function(n,t,e){var r;return t=v.createCallback(t,e,3),tr(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},v.findLast=function(n,t,e){var r;return t=v.createCallback(t,e,3),Nt(n,function(n,e,u){return t(n,e,u)?(r=n,false):void 0}),r},v.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=v.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;
+return-1},v.findLastKey=function(n,t,e){var r;return t=v.createCallback(t,e,3),bt(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},v.has=function(n,t){return n?we.call(n,t):false},v.identity=Ht,v.indexOf=zt,v.isArguments=dt,v.isArray=qe,v.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&he.call(n)==L||false},v.isDate=function(n){return n&&typeof n=="object"&&he.call(n)==z||false},v.isElement=function(n){return n&&1===n.nodeType||false},v.isEmpty=function(n){var t=true;if(!n)return t;var e=he.call(n),r=n.length;
+return e==$||e==M||(Le.argsClass?e==T:dt(n))||e==G&&typeof r=="number"&&jt(n.splice)?!r:(tr(n,function(){return t=false}),t)},v.isEqual=function(n,t,e,r){return at(n,t,typeof e=="function"&&tt(e,r,2))},v.isFinite=function(n){return Ie(n)&&!De(parseFloat(n))},v.isFunction=jt,v.isNaN=function(n){return Ct(n)&&n!=+n},v.isNull=function(n){return null===n},v.isNumber=Ct,v.isObject=xt,v.isPlainObject=er,v.isRegExp=function(n){return n&&X[typeof n]&&he.call(n)==J||false},v.isString=kt,v.isUndefined=function(n){return typeof n=="undefined"
+},v.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?Be(0,r+e):Pe(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},v.mixin=Ut,v.noConflict=function(){return e._=ge,this},v.noop=Qt,v.now=ir,v.parseInt=lr,v.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Fe(),Pe(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):lt(n,t)},v.reduce=Rt,v.reduceRight=Ft,v.result=function(n,t){if(n){var e=n[t];
+return jt(e)?n[t]():e}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:We(n).length},v.some=$t,v.sortedIndex=Kt,v.template=function(n,t,e){var r=v.templateSettings;n=ie(n||""),e=Ze({},e,r);var u,o=Ze({},e.imports,r.imports),r=We(o),o=Et(o),i=0,l=e.interpolate||N,f="__p+='",l=ae((e.escape||N).source+"|"+l.source+"|"+(l===I?O:N).source+"|"+(e.evaluate||N).source+"|$","g");n.replace(l,function(t,e,r,o,l,c){return r||(r=o),f+=n.slice(i,c).replace(P,a),e&&(f+="'+__e("+e+")+'"),l&&(u=true,f+="';"+l+";\n__p+='"),r&&(f+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t
+}),f+="';",l=e=e.variable,l||(e="obj",f="with("+e+"){"+f+"}"),f=(u?f.replace(x,""):f).replace(C,"$1").replace(E,"$1;"),f="function("+e+"){"+(l?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var c=ee(r,"return "+f).apply(h,o)}catch(p){throw p.source=f,p}return t?c(t):(c.source=f,c)},v.unescape=function(n){return null==n?"":ie(n).replace(Ue,mt)},v.uniqueId=function(n){var t=++m;return ie(null==n?"":n)+t
+},v.all=St,v.any=$t,v.detect=It,v.findWhere=It,v.foldl=Rt,v.foldr=Ft,v.include=Ot,v.inject=Rt,Ut(function(){var n={};return tr(v,function(t,e){v.prototype[e]||(n[e]=t)}),n}(),false),v.first=Lt,v.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:h;return s(n,Be(0,u-r))},v.sample=function(n,t,e){return n&&typeof n.length!="number"?n=Et(n):Le.unindexedChars&&kt(n)&&(n=n.split("")),null==t||e?n?n[lt(0,n.length-1)]:h:(n=Tt(n),n.length=Pe(Be(0,t),n.length),n)
+},v.take=Lt,v.head=Lt,tr(v,function(n,t){var e="sample"!==t;v.prototype[t]||(v.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new y(o,u):o})}),v.VERSION="2.4.1",v.prototype.chain=function(){return this.__chain__=true,this},v.prototype.toString=function(){return ie(this.__wrapped__)},v.prototype.value=Yt,v.prototype.valueOf=Yt,Xe(["join","pop","shift"],function(n){var t=fe[n];v.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);
+return n?new y(e,n):e}}),Xe(["push","reverse","sort","unshift"],function(n){var t=fe[n];v.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Xe(["concat","slice","splice"],function(n){var t=fe[n];v.prototype[n]=function(){return new y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Le.spliceObjects||Xe(["pop","shift","splice"],function(n){var t=fe[n],e="splice"==n;v.prototype[n]=function(){var n=this.__chain__,r=this.__wrapped__,u=t.apply(r,arguments);return 0===r.length&&delete r[0],n||e?new y(u,n):u
+}}),v}var h,v=[],y=[],m=0,d={},b=+new Date+"",_=75,w=40,j=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",x=/\b__p\+='';/g,C=/\b(__p\+=)''\+/g,E=/(__e\(.*?\)|\b__t\))\+'';/g,O=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,S=/\w*$/,A=/^\s*function[ \n\r\t]+\w/,I=/<%=([\s\S]+?)%>/g,D=RegExp("^["+j+"]*0+(?=.$)"),N=/($^)/,B=/\bthis\b/,P=/['\n\r\t\u2028\u2029\\]/g,R="Array Boolean Date Error Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setTimeout".split(" "),F="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),T="[object Arguments]",$="[object Array]",L="[object Boolean]",z="[object Date]",q="[object Error]",K="[object Function]",W="[object Number]",G="[object Object]",J="[object RegExp]",M="[object String]",V={};
+V[K]=false,V[T]=V[$]=V[L]=V[z]=V[W]=V[G]=V[J]=V[M]=true;var H={leading:false,maxWait:0,trailing:false},U={configurable:false,enumerable:false,value:null,writable:false},Q={a:"",b:null,c:"",d:"",e:"",v:null,g:"",h:null,support:null,i:"",j:false},X={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},Y={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},Z=X[typeof window]&&window||this,nt=X[typeof exports]&&exports&&!exports.nodeType&&exports,tt=X[typeof module]&&module&&!module.nodeType&&module,et=tt&&tt.exports===nt&&nt,rt=X[typeof global]&&global;
+!rt||rt.global!==rt&&rt.window!==rt||(Z=rt);var ut=g();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Z._=ut, define(function(){return ut})):nt&&tt?et?(tt.exports=ut)._=ut:nt._=ut:Z._=ut}).call(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.js	(revision 533)
@@ -0,0 +1,6785 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
+ * Build: `lodash modern -o ./dist/lodash.js`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function() {
+
+  /** Used as a safe reference for `undefined` in pre ES5 environments */
+  var undefined;
+
+  /** Used to pool arrays and objects used internally */
+  var arrayPool = [],
+      objectPool = [];
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
+  var keyPrefix = +new Date + '';
+
+  /** Used as the size when optimizations are enabled for large arrays */
+  var largeArraySize = 75;
+
+  /** Used as the max size of the `arrayPool` and `objectPool` */
+  var maxPoolSize = 40;
+
+  /** Used to detect and test whitespace */
+  var whitespace = (
+    // whitespace
+    ' \t\x0B\f\xA0\ufeff' +
+
+    // line terminators
+    '\n\r\u2028\u2029' +
+
+    // unicode category "Zs" space separators
+    '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
+  );
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detected named functions */
+  var reFuncName = /^\s*function[ \n\r\t]+\w/;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to match leading whitespace and zeros to be removed */
+  var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to detect functions containing a `this` reference */
+  var reThis = /\bthis\b/;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to assign default `context` object properties */
+  var contextProps = [
+    'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
+    'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
+    'parseInt', 'setTimeout'
+  ];
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Used to identify object classifications that `_.clone` supports */
+  var cloneableClasses = {};
+  cloneableClasses[funcClass] = false;
+  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
+  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
+  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
+
+  /** Used as an internal `_.debounce` options object */
+  var debounceOptions = {
+    'leading': false,
+    'maxWait': 0,
+    'trailing': false
+  };
+
+  /** Used as the property descriptor for `__bindData__` */
+  var descriptor = {
+    'configurable': false,
+    'enumerable': false,
+    'value': null,
+    'writable': false
+  };
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /** Used as a reference to the global object */
+  var root = (objectTypes[typeof window] && window) || this;
+
+  /** Detect free variable `exports` */
+  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+  /** Detect the popular CommonJS extension `module.exports` */
+  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+  /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
+  var freeGlobal = objectTypes[typeof global] && global;
+  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
+    root = freeGlobal;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The base implementation of `_.indexOf` without support for binary searches
+   * or `fromIndex` constraints.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {number} [fromIndex=0] The index to search from.
+   * @returns {number} Returns the index of the matched value or `-1`.
+   */
+  function baseIndexOf(array, value, fromIndex) {
+    var index = (fromIndex || 0) - 1,
+        length = array ? array.length : 0;
+
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * An implementation of `_.contains` for cache objects that mimics the return
+   * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
+   *
+   * @private
+   * @param {Object} cache The cache object to inspect.
+   * @param {*} value The value to search for.
+   * @returns {number} Returns `0` if `value` is found, else `-1`.
+   */
+  function cacheIndexOf(cache, value) {
+    var type = typeof value;
+    cache = cache.cache;
+
+    if (type == 'boolean' || value == null) {
+      return cache[value] ? 0 : -1;
+    }
+    if (type != 'number' && type != 'string') {
+      type = 'object';
+    }
+    var key = type == 'number' ? value : keyPrefix + value;
+    cache = (cache = cache[type]) && cache[key];
+
+    return type == 'object'
+      ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
+      : (cache ? 0 : -1);
+  }
+
+  /**
+   * Adds a given value to the corresponding cache object.
+   *
+   * @private
+   * @param {*} value The value to add to the cache.
+   */
+  function cachePush(value) {
+    var cache = this.cache,
+        type = typeof value;
+
+    if (type == 'boolean' || value == null) {
+      cache[value] = true;
+    } else {
+      if (type != 'number' && type != 'string') {
+        type = 'object';
+      }
+      var key = type == 'number' ? value : keyPrefix + value,
+          typeCache = cache[type] || (cache[type] = {});
+
+      if (type == 'object') {
+        (typeCache[key] || (typeCache[key] = [])).push(value);
+      } else {
+        typeCache[key] = true;
+      }
+    }
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default callback when a given
+   * collection is a string value.
+   *
+   * @private
+   * @param {string} value The character to inspect.
+   * @returns {number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` elements, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ac = a.criteria,
+        bc = b.criteria,
+        index = -1,
+        length = ac.length;
+
+    while (++index < length) {
+      var value = ac[index],
+          other = bc[index];
+
+      if (value !== other) {
+        if (value > other || typeof value == 'undefined') {
+          return 1;
+        }
+        if (value < other || typeof other == 'undefined') {
+          return -1;
+        }
+      }
+    }
+    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+    // that causes it, under certain circumstances, to return the same value for
+    // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
+    //
+    // This also ensures a stable sort in V8 and other engines.
+    // See http://code.google.com/p/v8/issues/detail?id=90
+    return a.index - b.index;
+  }
+
+  /**
+   * Creates a cache object to optimize linear searches of large arrays.
+   *
+   * @private
+   * @param {Array} [array=[]] The array to search.
+   * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
+   */
+  function createCache(array) {
+    var index = -1,
+        length = array.length,
+        first = array[0],
+        mid = array[(length / 2) | 0],
+        last = array[length - 1];
+
+    if (first && typeof first == 'object' &&
+        mid && typeof mid == 'object' && last && typeof last == 'object') {
+      return false;
+    }
+    var cache = getObject();
+    cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
+
+    var result = getObject();
+    result.array = array;
+    result.cache = cache;
+    result.push = cachePush;
+
+    while (++index < length) {
+      result.push(array[index]);
+    }
+    return result;
+  }
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {string} match The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Gets an array from the array pool or creates a new one if the pool is empty.
+   *
+   * @private
+   * @returns {Array} The array from the pool.
+   */
+  function getArray() {
+    return arrayPool.pop() || [];
+  }
+
+  /**
+   * Gets an object from the object pool or creates a new one if the pool is empty.
+   *
+   * @private
+   * @returns {Object} The object from the pool.
+   */
+  function getObject() {
+    return objectPool.pop() || {
+      'array': null,
+      'cache': null,
+      'criteria': null,
+      'false': false,
+      'index': 0,
+      'null': false,
+      'number': null,
+      'object': null,
+      'push': null,
+      'string': null,
+      'true': false,
+      'undefined': false,
+      'value': null
+    };
+  }
+
+  /**
+   * Releases the given array back to the array pool.
+   *
+   * @private
+   * @param {Array} [array] The array to release.
+   */
+  function releaseArray(array) {
+    array.length = 0;
+    if (arrayPool.length < maxPoolSize) {
+      arrayPool.push(array);
+    }
+  }
+
+  /**
+   * Releases the given object back to the object pool.
+   *
+   * @private
+   * @param {Object} [object] The object to release.
+   */
+  function releaseObject(object) {
+    var cache = object.cache;
+    if (cache) {
+      releaseObject(cache);
+    }
+    object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
+    if (objectPool.length < maxPoolSize) {
+      objectPool.push(object);
+    }
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used instead of `Array#slice` to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|string} collection The collection to slice.
+   * @param {number} start The start index.
+   * @param {number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Create a new `lodash` function using the given context object.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} [context=root] The context object.
+   * @returns {Function} Returns the `lodash` function.
+   */
+  function runInContext(context) {
+    // Avoid issues with some ES3 environments that attempt to use values, named
+    // after built-in constructors like `Object`, for the creation of literals.
+    // ES5 clears this up by stating that literals must use built-in constructors.
+    // See http://es5.github.io/#x11.1.5.
+    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+
+    /** Native constructor references */
+    var Array = context.Array,
+        Boolean = context.Boolean,
+        Date = context.Date,
+        Function = context.Function,
+        Math = context.Math,
+        Number = context.Number,
+        Object = context.Object,
+        RegExp = context.RegExp,
+        String = context.String,
+        TypeError = context.TypeError;
+
+    /**
+     * Used for `Array` method references.
+     *
+     * Normally `Array.prototype` would suffice, however, using an array literal
+     * avoids issues in Narwhal.
+     */
+    var arrayRef = [];
+
+    /** Used for native method references */
+    var objectProto = Object.prototype;
+
+    /** Used to restore the original `_` reference in `noConflict` */
+    var oldDash = context._;
+
+    /** Used to resolve the internal [[Class]] of values */
+    var toString = objectProto.toString;
+
+    /** Used to detect if a method is native */
+    var reNative = RegExp('^' +
+      String(toString)
+        .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+        .replace(/toString| for [^\]]+/g, '.*?') + '$'
+    );
+
+    /** Native method shortcuts */
+    var ceil = Math.ceil,
+        clearTimeout = context.clearTimeout,
+        floor = Math.floor,
+        fnToString = Function.prototype.toString,
+        getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+        hasOwnProperty = objectProto.hasOwnProperty,
+        push = arrayRef.push,
+        setTimeout = context.setTimeout,
+        splice = arrayRef.splice,
+        unshift = arrayRef.unshift;
+
+    /** Used to set meta data on functions */
+    var defineProperty = (function() {
+      // IE 8 only accepts DOM elements
+      try {
+        var o = {},
+            func = isNative(func = Object.defineProperty) && func,
+            result = func(o, o, o) && func;
+      } catch(e) { }
+      return result;
+    }());
+
+    /* Native method shortcuts for methods with the same name as other `lodash` methods */
+    var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
+        nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
+        nativeIsFinite = context.isFinite,
+        nativeIsNaN = context.isNaN,
+        nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
+        nativeMax = Math.max,
+        nativeMin = Math.min,
+        nativeParseInt = context.parseInt,
+        nativeRandom = Math.random;
+
+    /** Used to lookup a built-in constructor by [[Class]] */
+    var ctorByClass = {};
+    ctorByClass[arrayClass] = Array;
+    ctorByClass[boolClass] = Boolean;
+    ctorByClass[dateClass] = Date;
+    ctorByClass[funcClass] = Function;
+    ctorByClass[objectClass] = Object;
+    ctorByClass[numberClass] = Number;
+    ctorByClass[regexpClass] = RegExp;
+    ctorByClass[stringClass] = String;
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object which wraps the given value to enable intuitive
+     * method chaining.
+     *
+     * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+     * and `unshift`
+     *
+     * Chaining is supported in custom builds as long as the `value` method is
+     * implicitly or explicitly included in the build.
+     *
+     * The chainable wrapper functions are:
+     * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
+     * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
+     * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
+     * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
+     * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
+     * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
+     * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
+     * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
+     * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
+     * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
+     * and `zip`
+     *
+     * The non-chainable wrapper functions are:
+     * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
+     * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
+     * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
+     * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
+     * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
+     * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
+     * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
+     * `template`, `unescape`, `uniqueId`, and `value`
+     *
+     * The wrapper functions `first` and `last` return wrapped values when `n` is
+     * provided, otherwise they return unwrapped values.
+     *
+     * Explicit chaining can be enabled by using the `_.chain` method.
+     *
+     * @name _
+     * @constructor
+     * @category Chaining
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @returns {Object} Returns a `lodash` instance.
+     * @example
+     *
+     * var wrapped = _([1, 2, 3]);
+     *
+     * // returns an unwrapped value
+     * wrapped.reduce(function(sum, num) {
+     *   return sum + num;
+     * });
+     * // => 6
+     *
+     * // returns a wrapped value
+     * var squares = wrapped.map(function(num) {
+     *   return num * num;
+     * });
+     *
+     * _.isArray(squares);
+     * // => false
+     *
+     * _.isArray(squares.value());
+     * // => true
+     */
+    function lodash(value) {
+      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
+      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
+       ? value
+       : new lodashWrapper(value);
+    }
+
+    /**
+     * A fast path for creating `lodash` wrapper objects.
+     *
+     * @private
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @param {boolean} chainAll A flag to enable chaining for all methods
+     * @returns {Object} Returns a `lodash` instance.
+     */
+    function lodashWrapper(value, chainAll) {
+      this.__chain__ = !!chainAll;
+      this.__wrapped__ = value;
+    }
+    // ensure `new lodashWrapper` is an instance of `lodash`
+    lodashWrapper.prototype = lodash.prototype;
+
+    /**
+     * An object used to flag environments features.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    var support = lodash.support = {};
+
+    /**
+     * Detect if functions can be decompiled by `Function#toString`
+     * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
+     *
+     * @memberOf _.support
+     * @type boolean
+     */
+    support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
+
+    /**
+     * Detect if `Function#name` is supported (all but IE).
+     *
+     * @memberOf _.support
+     * @type boolean
+     */
+    support.funcNames = typeof Function.name == 'string';
+
+    /**
+     * By default, the template delimiters used by Lo-Dash are similar to those in
+     * embedded Ruby (ERB). Change the following template settings to use alternative
+     * delimiters.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    lodash.templateSettings = {
+
+      /**
+       * Used to detect `data` property values to be HTML-escaped.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'escape': /<%-([\s\S]+?)%>/g,
+
+      /**
+       * Used to detect code to be evaluated.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'evaluate': /<%([\s\S]+?)%>/g,
+
+      /**
+       * Used to detect `data` property values to inject.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'interpolate': reInterpolate,
+
+      /**
+       * Used to reference the data object in the template text.
+       *
+       * @memberOf _.templateSettings
+       * @type string
+       */
+      'variable': '',
+
+      /**
+       * Used to import variables into the compiled template.
+       *
+       * @memberOf _.templateSettings
+       * @type Object
+       */
+      'imports': {
+
+        /**
+         * A reference to the `lodash` function.
+         *
+         * @memberOf _.templateSettings.imports
+         * @type Function
+         */
+        '_': lodash
+      }
+    };
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The base implementation of `_.bind` that creates the bound function and
+     * sets its meta data.
+     *
+     * @private
+     * @param {Array} bindData The bind data array.
+     * @returns {Function} Returns the new bound function.
+     */
+    function baseBind(bindData) {
+      var func = bindData[0],
+          partialArgs = bindData[2],
+          thisArg = bindData[4];
+
+      function bound() {
+        // `Function#bind` spec
+        // http://es5.github.io/#x15.3.4.5
+        if (partialArgs) {
+          // avoid `arguments` object deoptimizations by using `slice` instead
+          // of `Array.prototype.slice.call` and not assigning `arguments` to a
+          // variable as a ternary expression
+          var args = slice(partialArgs);
+          push.apply(args, arguments);
+        }
+        // mimic the constructor's `return` behavior
+        // http://es5.github.io/#x13.2.2
+        if (this instanceof bound) {
+          // ensure `new bound` is an instance of `func`
+          var thisBinding = baseCreate(func.prototype),
+              result = func.apply(thisBinding, args || arguments);
+          return isObject(result) ? result : thisBinding;
+        }
+        return func.apply(thisArg, args || arguments);
+      }
+      setBindData(bound, bindData);
+      return bound;
+    }
+
+    /**
+     * The base implementation of `_.clone` without argument juggling or support
+     * for `thisArg` binding.
+     *
+     * @private
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep=false] Specify a deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates clones with source counterparts.
+     * @returns {*} Returns the cloned value.
+     */
+    function baseClone(value, isDeep, callback, stackA, stackB) {
+      if (callback) {
+        var result = callback(value);
+        if (typeof result != 'undefined') {
+          return result;
+        }
+      }
+      // inspect [[Class]]
+      var isObj = isObject(value);
+      if (isObj) {
+        var className = toString.call(value);
+        if (!cloneableClasses[className]) {
+          return value;
+        }
+        var ctor = ctorByClass[className];
+        switch (className) {
+          case boolClass:
+          case dateClass:
+            return new ctor(+value);
+
+          case numberClass:
+          case stringClass:
+            return new ctor(value);
+
+          case regexpClass:
+            result = ctor(value.source, reFlags.exec(value));
+            result.lastIndex = value.lastIndex;
+            return result;
+        }
+      } else {
+        return value;
+      }
+      var isArr = isArray(value);
+      if (isDeep) {
+        // check for circular references and return corresponding clone
+        var initedStack = !stackA;
+        stackA || (stackA = getArray());
+        stackB || (stackB = getArray());
+
+        var length = stackA.length;
+        while (length--) {
+          if (stackA[length] == value) {
+            return stackB[length];
+          }
+        }
+        result = isArr ? ctor(value.length) : {};
+      }
+      else {
+        result = isArr ? slice(value) : assign({}, value);
+      }
+      // add array properties assigned by `RegExp#exec`
+      if (isArr) {
+        if (hasOwnProperty.call(value, 'index')) {
+          result.index = value.index;
+        }
+        if (hasOwnProperty.call(value, 'input')) {
+          result.input = value.input;
+        }
+      }
+      // exit for shallow clone
+      if (!isDeep) {
+        return result;
+      }
+      // add the source value to the stack of traversed objects
+      // and associate it with its clone
+      stackA.push(value);
+      stackB.push(result);
+
+      // recursively populate clone (susceptible to call stack limits)
+      (isArr ? forEach : forOwn)(value, function(objValue, key) {
+        result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
+      });
+
+      if (initedStack) {
+        releaseArray(stackA);
+        releaseArray(stackB);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.create` without support for assigning
+     * properties to the created object.
+     *
+     * @private
+     * @param {Object} prototype The object to inherit from.
+     * @returns {Object} Returns the new object.
+     */
+    function baseCreate(prototype, properties) {
+      return isObject(prototype) ? nativeCreate(prototype) : {};
+    }
+    // fallback for browsers without `Object.create`
+    if (!nativeCreate) {
+      baseCreate = (function() {
+        function Object() {}
+        return function(prototype) {
+          if (isObject(prototype)) {
+            Object.prototype = prototype;
+            var result = new Object;
+            Object.prototype = null;
+          }
+          return result || context.Object();
+        };
+      }());
+    }
+
+    /**
+     * The base implementation of `_.createCallback` without support for creating
+     * "_.pluck" or "_.where" style callbacks.
+     *
+     * @private
+     * @param {*} [func=identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of the created callback.
+     * @param {number} [argCount] The number of arguments the callback accepts.
+     * @returns {Function} Returns a callback function.
+     */
+    function baseCreateCallback(func, thisArg, argCount) {
+      if (typeof func != 'function') {
+        return identity;
+      }
+      // exit early for no `thisArg` or already bound by `Function#bind`
+      if (typeof thisArg == 'undefined' || !('prototype' in func)) {
+        return func;
+      }
+      var bindData = func.__bindData__;
+      if (typeof bindData == 'undefined') {
+        if (support.funcNames) {
+          bindData = !func.name;
+        }
+        bindData = bindData || !support.funcDecomp;
+        if (!bindData) {
+          var source = fnToString.call(func);
+          if (!support.funcNames) {
+            bindData = !reFuncName.test(source);
+          }
+          if (!bindData) {
+            // checks if `func` references the `this` keyword and stores the result
+            bindData = reThis.test(source);
+            setBindData(func, bindData);
+          }
+        }
+      }
+      // exit early if there are no `this` references or `func` is bound
+      if (bindData === false || (bindData !== true && bindData[1] & 1)) {
+        return func;
+      }
+      switch (argCount) {
+        case 1: return function(value) {
+          return func.call(thisArg, value);
+        };
+        case 2: return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+        case 3: return function(value, index, collection) {
+          return func.call(thisArg, value, index, collection);
+        };
+        case 4: return function(accumulator, value, index, collection) {
+          return func.call(thisArg, accumulator, value, index, collection);
+        };
+      }
+      return bind(func, thisArg);
+    }
+
+    /**
+     * The base implementation of `createWrapper` that creates the wrapper and
+     * sets its meta data.
+     *
+     * @private
+     * @param {Array} bindData The bind data array.
+     * @returns {Function} Returns the new function.
+     */
+    function baseCreateWrapper(bindData) {
+      var func = bindData[0],
+          bitmask = bindData[1],
+          partialArgs = bindData[2],
+          partialRightArgs = bindData[3],
+          thisArg = bindData[4],
+          arity = bindData[5];
+
+      var isBind = bitmask & 1,
+          isBindKey = bitmask & 2,
+          isCurry = bitmask & 4,
+          isCurryBound = bitmask & 8,
+          key = func;
+
+      function bound() {
+        var thisBinding = isBind ? thisArg : this;
+        if (partialArgs) {
+          var args = slice(partialArgs);
+          push.apply(args, arguments);
+        }
+        if (partialRightArgs || isCurry) {
+          args || (args = slice(arguments));
+          if (partialRightArgs) {
+            push.apply(args, partialRightArgs);
+          }
+          if (isCurry && args.length < arity) {
+            bitmask |= 16 & ~32;
+            return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
+          }
+        }
+        args || (args = arguments);
+        if (isBindKey) {
+          func = thisBinding[key];
+        }
+        if (this instanceof bound) {
+          thisBinding = baseCreate(func.prototype);
+          var result = func.apply(thisBinding, args);
+          return isObject(result) ? result : thisBinding;
+        }
+        return func.apply(thisBinding, args);
+      }
+      setBindData(bound, bindData);
+      return bound;
+    }
+
+    /**
+     * The base implementation of `_.difference` that accepts a single array
+     * of values to exclude.
+     *
+     * @private
+     * @param {Array} array The array to process.
+     * @param {Array} [values] The array of values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     */
+    function baseDifference(array, values) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array ? array.length : 0,
+          isLarge = length >= largeArraySize && indexOf === baseIndexOf,
+          result = [];
+
+      if (isLarge) {
+        var cache = createCache(values);
+        if (cache) {
+          indexOf = cacheIndexOf;
+          values = cache;
+        } else {
+          isLarge = false;
+        }
+      }
+      while (++index < length) {
+        var value = array[index];
+        if (indexOf(values, value) < 0) {
+          result.push(value);
+        }
+      }
+      if (isLarge) {
+        releaseObject(values);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.flatten` without support for callback
+     * shorthands or `thisArg` binding.
+     *
+     * @private
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+     * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
+     * @param {number} [fromIndex=0] The index to start from.
+     * @returns {Array} Returns a new flattened array.
+     */
+    function baseFlatten(array, isShallow, isStrict, fromIndex) {
+      var index = (fromIndex || 0) - 1,
+          length = array ? array.length : 0,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+
+        if (value && typeof value == 'object' && typeof value.length == 'number'
+            && (isArray(value) || isArguments(value))) {
+          // recursively flatten arrays (susceptible to call stack limits)
+          if (!isShallow) {
+            value = baseFlatten(value, isShallow, isStrict);
+          }
+          var valIndex = -1,
+              valLength = value.length,
+              resIndex = result.length;
+
+          result.length += valLength;
+          while (++valIndex < valLength) {
+            result[resIndex++] = value[valIndex];
+          }
+        } else if (!isStrict) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.isEqual`, without support for `thisArg` binding,
+     * that allows partial "_.where" style comparisons.
+     *
+     * @private
+     * @param {*} a The value to compare.
+     * @param {*} b The other value to compare.
+     * @param {Function} [callback] The function to customize comparing values.
+     * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
+     * @param {Array} [stackA=[]] Tracks traversed `a` objects.
+     * @param {Array} [stackB=[]] Tracks traversed `b` objects.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     */
+    function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
+      // used to indicate that when comparing objects, `a` has at least the properties of `b`
+      if (callback) {
+        var result = callback(a, b);
+        if (typeof result != 'undefined') {
+          return !!result;
+        }
+      }
+      // exit early for identical values
+      if (a === b) {
+        // treat `+0` vs. `-0` as not equal
+        return a !== 0 || (1 / a == 1 / b);
+      }
+      var type = typeof a,
+          otherType = typeof b;
+
+      // exit early for unlike primitive values
+      if (a === a &&
+          !(a && objectTypes[type]) &&
+          !(b && objectTypes[otherType])) {
+        return false;
+      }
+      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
+      // http://es5.github.io/#x15.3.4.4
+      if (a == null || b == null) {
+        return a === b;
+      }
+      // compare [[Class]] names
+      var className = toString.call(a),
+          otherClass = toString.call(b);
+
+      if (className == argsClass) {
+        className = objectClass;
+      }
+      if (otherClass == argsClass) {
+        otherClass = objectClass;
+      }
+      if (className != otherClass) {
+        return false;
+      }
+      switch (className) {
+        case boolClass:
+        case dateClass:
+          // coerce dates and booleans to numbers, dates to milliseconds and booleans
+          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
+          return +a == +b;
+
+        case numberClass:
+          // treat `NaN` vs. `NaN` as equal
+          return (a != +a)
+            ? b != +b
+            // but treat `+0` vs. `-0` as not equal
+            : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+        case regexpClass:
+        case stringClass:
+          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
+          // treat string primitives and their corresponding object instances as equal
+          return a == String(b);
+      }
+      var isArr = className == arrayClass;
+      if (!isArr) {
+        // unwrap any `lodash` wrapped values
+        var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
+            bWrapped = hasOwnProperty.call(b, '__wrapped__');
+
+        if (aWrapped || bWrapped) {
+          return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
+        }
+        // exit for functions and DOM nodes
+        if (className != objectClass) {
+          return false;
+        }
+        // in older versions of Opera, `arguments` objects have `Array` constructors
+        var ctorA = a.constructor,
+            ctorB = b.constructor;
+
+        // non `Object` object instances with different constructors are not equal
+        if (ctorA != ctorB &&
+              !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
+              ('constructor' in a && 'constructor' in b)
+            ) {
+          return false;
+        }
+      }
+      // assume cyclic structures are equal
+      // the algorithm for detecting cyclic structures is adapted from ES 5.1
+      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
+      var initedStack = !stackA;
+      stackA || (stackA = getArray());
+      stackB || (stackB = getArray());
+
+      var length = stackA.length;
+      while (length--) {
+        if (stackA[length] == a) {
+          return stackB[length] == b;
+        }
+      }
+      var size = 0;
+      result = true;
+
+      // add `a` and `b` to the stack of traversed objects
+      stackA.push(a);
+      stackB.push(b);
+
+      // recursively compare objects and arrays (susceptible to call stack limits)
+      if (isArr) {
+        // compare lengths to determine if a deep comparison is necessary
+        length = a.length;
+        size = b.length;
+        result = size == length;
+
+        if (result || isWhere) {
+          // deep compare the contents, ignoring non-numeric properties
+          while (size--) {
+            var index = length,
+                value = b[size];
+
+            if (isWhere) {
+              while (index--) {
+                if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
+                  break;
+                }
+              }
+            } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
+              break;
+            }
+          }
+        }
+      }
+      else {
+        // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
+        // which, in this case, is more costly
+        forIn(b, function(value, key, b) {
+          if (hasOwnProperty.call(b, key)) {
+            // count the number of properties.
+            size++;
+            // deep compare each property value.
+            return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
+          }
+        });
+
+        if (result && !isWhere) {
+          // ensure both objects have the same number of properties
+          forIn(a, function(value, key, a) {
+            if (hasOwnProperty.call(a, key)) {
+              // `size` will be `-1` if `a` has more properties than `b`
+              return (result = --size > -1);
+            }
+          });
+        }
+      }
+      stackA.pop();
+      stackB.pop();
+
+      if (initedStack) {
+        releaseArray(stackA);
+        releaseArray(stackB);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.merge` without argument juggling or support
+     * for `thisArg` binding.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @param {Function} [callback] The function to customize merging properties.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates values with source counterparts.
+     */
+    function baseMerge(object, source, callback, stackA, stackB) {
+      (isArray(source) ? forEach : forOwn)(source, function(source, key) {
+        var found,
+            isArr,
+            result = source,
+            value = object[key];
+
+        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+          // avoid merging previously merged cyclic sources
+          var stackLength = stackA.length;
+          while (stackLength--) {
+            if ((found = stackA[stackLength] == source)) {
+              value = stackB[stackLength];
+              break;
+            }
+          }
+          if (!found) {
+            var isShallow;
+            if (callback) {
+              result = callback(value, source);
+              if ((isShallow = typeof result != 'undefined')) {
+                value = result;
+              }
+            }
+            if (!isShallow) {
+              value = isArr
+                ? (isArray(value) ? value : [])
+                : (isPlainObject(value) ? value : {});
+            }
+            // add `source` and associated `value` to the stack of traversed objects
+            stackA.push(source);
+            stackB.push(value);
+
+            // recursively merge objects and arrays (susceptible to call stack limits)
+            if (!isShallow) {
+              baseMerge(value, source, callback, stackA, stackB);
+            }
+          }
+        }
+        else {
+          if (callback) {
+            result = callback(value, source);
+            if (typeof result == 'undefined') {
+              result = source;
+            }
+          }
+          if (typeof result != 'undefined') {
+            value = result;
+          }
+        }
+        object[key] = value;
+      });
+    }
+
+    /**
+     * The base implementation of `_.random` without argument juggling or support
+     * for returning floating-point numbers.
+     *
+     * @private
+     * @param {number} min The minimum possible value.
+     * @param {number} max The maximum possible value.
+     * @returns {number} Returns a random number.
+     */
+    function baseRandom(min, max) {
+      return min + floor(nativeRandom() * (max - min + 1));
+    }
+
+    /**
+     * The base implementation of `_.uniq` without support for callback shorthands
+     * or `thisArg` binding.
+     *
+     * @private
+     * @param {Array} array The array to process.
+     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+     * @param {Function} [callback] The function called per iteration.
+     * @returns {Array} Returns a duplicate-value-free array.
+     */
+    function baseUniq(array, isSorted, callback) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array ? array.length : 0,
+          result = [];
+
+      var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
+          seen = (callback || isLarge) ? getArray() : result;
+
+      if (isLarge) {
+        var cache = createCache(seen);
+        indexOf = cacheIndexOf;
+        seen = cache;
+      }
+      while (++index < length) {
+        var value = array[index],
+            computed = callback ? callback(value, index, array) : value;
+
+        if (isSorted
+              ? !index || seen[seen.length - 1] !== computed
+              : indexOf(seen, computed) < 0
+            ) {
+          if (callback || isLarge) {
+            seen.push(computed);
+          }
+          result.push(value);
+        }
+      }
+      if (isLarge) {
+        releaseArray(seen.array);
+        releaseObject(seen);
+      } else if (callback) {
+        releaseArray(seen);
+      }
+      return result;
+    }
+
+    /**
+     * Creates a function that aggregates a collection, creating an object composed
+     * of keys generated from the results of running each element of the collection
+     * through a callback. The given `setter` function sets the keys and values
+     * of the composed object.
+     *
+     * @private
+     * @param {Function} setter The setter function.
+     * @returns {Function} Returns the new aggregator function.
+     */
+    function createAggregator(setter) {
+      return function(collection, callback, thisArg) {
+        var result = {};
+        callback = lodash.createCallback(callback, thisArg, 3);
+
+        var index = -1,
+            length = collection ? collection.length : 0;
+
+        if (typeof length == 'number') {
+          while (++index < length) {
+            var value = collection[index];
+            setter(result, value, callback(value, index, collection), collection);
+          }
+        } else {
+          forOwn(collection, function(value, key, collection) {
+            setter(result, value, callback(value, key, collection), collection);
+          });
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that, when called, either curries or invokes `func`
+     * with an optional `this` binding and partially applied arguments.
+     *
+     * @private
+     * @param {Function|string} func The function or method name to reference.
+     * @param {number} bitmask The bitmask of method flags to compose.
+     *  The bitmask may be composed of the following flags:
+     *  1 - `_.bind`
+     *  2 - `_.bindKey`
+     *  4 - `_.curry`
+     *  8 - `_.curry` (bound)
+     *  16 - `_.partial`
+     *  32 - `_.partialRight`
+     * @param {Array} [partialArgs] An array of arguments to prepend to those
+     *  provided to the new function.
+     * @param {Array} [partialRightArgs] An array of arguments to append to those
+     *  provided to the new function.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {number} [arity] The arity of `func`.
+     * @returns {Function} Returns the new function.
+     */
+    function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
+      var isBind = bitmask & 1,
+          isBindKey = bitmask & 2,
+          isCurry = bitmask & 4,
+          isCurryBound = bitmask & 8,
+          isPartial = bitmask & 16,
+          isPartialRight = bitmask & 32;
+
+      if (!isBindKey && !isFunction(func)) {
+        throw new TypeError;
+      }
+      if (isPartial && !partialArgs.length) {
+        bitmask &= ~16;
+        isPartial = partialArgs = false;
+      }
+      if (isPartialRight && !partialRightArgs.length) {
+        bitmask &= ~32;
+        isPartialRight = partialRightArgs = false;
+      }
+      var bindData = func && func.__bindData__;
+      if (bindData && bindData !== true) {
+        // clone `bindData`
+        bindData = slice(bindData);
+        if (bindData[2]) {
+          bindData[2] = slice(bindData[2]);
+        }
+        if (bindData[3]) {
+          bindData[3] = slice(bindData[3]);
+        }
+        // set `thisBinding` is not previously bound
+        if (isBind && !(bindData[1] & 1)) {
+          bindData[4] = thisArg;
+        }
+        // set if previously bound but not currently (subsequent curried functions)
+        if (!isBind && bindData[1] & 1) {
+          bitmask |= 8;
+        }
+        // set curried arity if not yet set
+        if (isCurry && !(bindData[1] & 4)) {
+          bindData[5] = arity;
+        }
+        // append partial left arguments
+        if (isPartial) {
+          push.apply(bindData[2] || (bindData[2] = []), partialArgs);
+        }
+        // append partial right arguments
+        if (isPartialRight) {
+          unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
+        }
+        // merge flags
+        bindData[1] |= bitmask;
+        return createWrapper.apply(null, bindData);
+      }
+      // fast path for `_.bind`
+      var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
+      return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
+    }
+
+    /**
+     * Used by `escape` to convert characters to HTML entities.
+     *
+     * @private
+     * @param {string} match The matched character to escape.
+     * @returns {string} Returns the escaped character.
+     */
+    function escapeHtmlChar(match) {
+      return htmlEscapes[match];
+    }
+
+    /**
+     * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+     * customized, this method returns the custom method, otherwise it returns
+     * the `baseIndexOf` function.
+     *
+     * @private
+     * @returns {Function} Returns the "indexOf" function.
+     */
+    function getIndexOf() {
+      var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
+      return result;
+    }
+
+    /**
+     * Checks if `value` is a native function.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
+     */
+    function isNative(value) {
+      return typeof value == 'function' && reNative.test(value);
+    }
+
+    /**
+     * Sets `this` binding data on a given function.
+     *
+     * @private
+     * @param {Function} func The function to set data on.
+     * @param {Array} value The data array to set.
+     */
+    var setBindData = !defineProperty ? noop : function(func, value) {
+      descriptor.value = value;
+      defineProperty(func, '__bindData__', descriptor);
+    };
+
+    /**
+     * A fallback implementation of `isPlainObject` which checks if a given value
+     * is an object created by the `Object` constructor, assuming objects created
+     * by the `Object` constructor have no inherited enumerable properties and that
+     * there are no `Object.prototype` extensions.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     */
+    function shimIsPlainObject(value) {
+      var ctor,
+          result;
+
+      // avoid non Object objects, `arguments` objects, and DOM elements
+      if (!(value && toString.call(value) == objectClass) ||
+          (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
+        return false;
+      }
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return typeof result == 'undefined' || hasOwnProperty.call(value, result);
+    }
+
+    /**
+     * Used by `unescape` to convert HTML entities to characters.
+     *
+     * @private
+     * @param {string} match The matched character to unescape.
+     * @returns {string} Returns the unescaped character.
+     */
+    function unescapeHtmlChar(match) {
+      return htmlUnescapes[match];
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Checks if `value` is an `arguments` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+     * @example
+     *
+     * (function() { return _.isArguments(arguments); })(1, 2, 3);
+     * // => true
+     *
+     * _.isArguments([1, 2, 3]);
+     * // => false
+     */
+    function isArguments(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        toString.call(value) == argsClass || false;
+    }
+
+    /**
+     * Checks if `value` is an array.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
+     * @example
+     *
+     * (function() { return _.isArray(arguments); })();
+     * // => false
+     *
+     * _.isArray([1, 2, 3]);
+     * // => true
+     */
+    var isArray = nativeIsArray || function(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        toString.call(value) == arrayClass || false;
+    };
+
+    /**
+     * A fallback implementation of `Object.keys` which produces an array of the
+     * given object's own enumerable property names.
+     *
+     * @private
+     * @type Function
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names.
+     */
+    var shimKeys = function(object) {
+      var index, iterable = object, result = [];
+      if (!iterable) return result;
+      if (!(objectTypes[typeof object])) return result;
+        for (index in iterable) {
+          if (hasOwnProperty.call(iterable, index)) {
+            result.push(index);
+          }
+        }
+      return result
+    };
+
+    /**
+     * Creates an array composed of the own enumerable property names of an object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names.
+     * @example
+     *
+     * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
+     */
+    var keys = !nativeKeys ? shimKeys : function(object) {
+      if (!isObject(object)) {
+        return [];
+      }
+      return nativeKeys(object);
+    };
+
+    /**
+     * Used to convert characters to HTML entities:
+     *
+     * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+     * don't require escaping in HTML and have no special meaning unless they're part
+     * of a tag or an unquoted attribute value.
+     * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+     */
+    var htmlEscapes = {
+      '&': '&amp;',
+      '<': '&lt;',
+      '>': '&gt;',
+      '"': '&quot;',
+      "'": '&#39;'
+    };
+
+    /** Used to convert HTML entities to characters */
+    var htmlUnescapes = invert(htmlEscapes);
+
+    /** Used to match HTML entities and HTML characters */
+    var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
+        reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object. Subsequent sources will overwrite property assignments of previous
+     * sources. If a callback is provided it will be executed to produce the
+     * assigned values. The callback is bound to `thisArg` and invoked with two
+     * arguments; (objectValue, sourceValue).
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @alias extend
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param {Function} [callback] The function to customize assigning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
+     * // => { 'name': 'fred', 'employer': 'slate' }
+     *
+     * var defaults = _.partialRight(_.assign, function(a, b) {
+     *   return typeof a == 'undefined' ? b : a;
+     * });
+     *
+     * var object = { 'name': 'barney' };
+     * defaults(object, { 'name': 'fred', 'employer': 'slate' });
+     * // => { 'name': 'barney', 'employer': 'slate' }
+     */
+    var assign = function(object, source, guard) {
+      var index, iterable = object, result = iterable;
+      if (!iterable) return result;
+      var args = arguments,
+          argsIndex = 0,
+          argsLength = typeof guard == 'number' ? 2 : args.length;
+      if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
+        var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
+      } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
+        callback = args[--argsLength];
+      }
+      while (++argsIndex < argsLength) {
+        iterable = args[argsIndex];
+        if (iterable && objectTypes[typeof iterable]) {
+        var ownIndex = -1,
+            ownProps = objectTypes[typeof iterable] && keys(iterable),
+            length = ownProps ? ownProps.length : 0;
+
+        while (++ownIndex < length) {
+          index = ownProps[ownIndex];
+          result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
+        }
+        }
+      }
+      return result
+    };
+
+    /**
+     * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
+     * be cloned, otherwise they will be assigned by reference. If a callback
+     * is provided it will be executed to produce the cloned values. If the
+     * callback returns `undefined` cloning will be handled by the method instead.
+     * The callback is bound to `thisArg` and invoked with one argument; (value).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep=false] Specify a deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the cloned value.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * var shallow = _.clone(characters);
+     * shallow[0] === characters[0];
+     * // => true
+     *
+     * var deep = _.clone(characters, true);
+     * deep[0] === characters[0];
+     * // => false
+     *
+     * _.mixin({
+     *   'clone': _.partialRight(_.clone, function(value) {
+     *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+     *   })
+     * });
+     *
+     * var clone = _.clone(document.body);
+     * clone.childNodes.length;
+     * // => 0
+     */
+    function clone(value, isDeep, callback, thisArg) {
+      // allows working with "Collections" methods without using their `index`
+      // and `collection` arguments for `isDeep` and `callback`
+      if (typeof isDeep != 'boolean' && isDeep != null) {
+        thisArg = callback;
+        callback = isDeep;
+        isDeep = false;
+      }
+      return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+    }
+
+    /**
+     * Creates a deep clone of `value`. If a callback is provided it will be
+     * executed to produce the cloned values. If the callback returns `undefined`
+     * cloning will be handled by the method instead. The callback is bound to
+     * `thisArg` and invoked with one argument; (value).
+     *
+     * Note: This method is loosely based on the structured clone algorithm. Functions
+     * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+     * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+     * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the deep cloned value.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * var deep = _.cloneDeep(characters);
+     * deep[0] === characters[0];
+     * // => false
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'node': element
+     * };
+     *
+     * var clone = _.cloneDeep(view, function(value) {
+     *   return _.isElement(value) ? value.cloneNode(true) : undefined;
+     * });
+     *
+     * clone.node == view.node;
+     * // => false
+     */
+    function cloneDeep(value, callback, thisArg) {
+      return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+    }
+
+    /**
+     * Creates an object that inherits from the given `prototype` object. If a
+     * `properties` object is provided its own enumerable properties are assigned
+     * to the created object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} prototype The object to inherit from.
+     * @param {Object} [properties] The properties to assign to the object.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * function Circle() {
+     *   Shape.call(this);
+     * }
+     *
+     * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
+     *
+     * var circle = new Circle;
+     * circle instanceof Circle;
+     * // => true
+     *
+     * circle instanceof Shape;
+     * // => true
+     */
+    function create(prototype, properties) {
+      var result = baseCreate(prototype);
+      return properties ? assign(result, properties) : result;
+    }
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object for all destination properties that resolve to `undefined`. Once a
+     * property is set, additional defaults of the same property will be ignored.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param- {Object} [guard] Allows working with `_.reduce` without using its
+     *  `key` and `object` arguments as sources.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * var object = { 'name': 'barney' };
+     * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
+     * // => { 'name': 'barney', 'employer': 'slate' }
+     */
+    var defaults = function(object, source, guard) {
+      var index, iterable = object, result = iterable;
+      if (!iterable) return result;
+      var args = arguments,
+          argsIndex = 0,
+          argsLength = typeof guard == 'number' ? 2 : args.length;
+      while (++argsIndex < argsLength) {
+        iterable = args[argsIndex];
+        if (iterable && objectTypes[typeof iterable]) {
+        var ownIndex = -1,
+            ownProps = objectTypes[typeof iterable] && keys(iterable),
+            length = ownProps ? ownProps.length : 0;
+
+        while (++ownIndex < length) {
+          index = ownProps[ownIndex];
+          if (typeof result[index] == 'undefined') result[index] = iterable[index];
+        }
+        }
+      }
+      return result
+    };
+
+    /**
+     * This method is like `_.findIndex` except that it returns the key of the
+     * first element that passes the callback check, instead of the element itself.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [callback=identity] The function called per
+     *  iteration. If a property name or object is provided it will be used to
+     *  create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
+     * @example
+     *
+     * var characters = {
+     *   'barney': {  'age': 36, 'blocked': false },
+     *   'fred': {    'age': 40, 'blocked': true },
+     *   'pebbles': { 'age': 1,  'blocked': false }
+     * };
+     *
+     * _.findKey(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => 'barney' (property order is not guaranteed across environments)
+     *
+     * // using "_.where" callback shorthand
+     * _.findKey(characters, { 'age': 1 });
+     * // => 'pebbles'
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findKey(characters, 'blocked');
+     * // => 'fred'
+     */
+    function findKey(object, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forOwn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result = key;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * This method is like `_.findKey` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [callback=identity] The function called per
+     *  iteration. If a property name or object is provided it will be used to
+     *  create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
+     * @example
+     *
+     * var characters = {
+     *   'barney': {  'age': 36, 'blocked': true },
+     *   'fred': {    'age': 40, 'blocked': false },
+     *   'pebbles': { 'age': 1,  'blocked': true }
+     * };
+     *
+     * _.findLastKey(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => returns `pebbles`, assuming `_.findKey` returns `barney`
+     *
+     * // using "_.where" callback shorthand
+     * _.findLastKey(characters, { 'age': 40 });
+     * // => 'fred'
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findLastKey(characters, 'blocked');
+     * // => 'pebbles'
+     */
+    function findLastKey(object, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forOwnRight(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result = key;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Iterates over own and inherited enumerable properties of an object,
+     * executing the callback for each property. The callback is bound to `thisArg`
+     * and invoked with three arguments; (value, key, object). Callbacks may exit
+     * iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * Shape.prototype.move = function(x, y) {
+     *   this.x += x;
+     *   this.y += y;
+     * };
+     *
+     * _.forIn(new Shape, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
+     */
+    var forIn = function(collection, callback, thisArg) {
+      var index, iterable = collection, result = iterable;
+      if (!iterable) return result;
+      if (!objectTypes[typeof iterable]) return result;
+      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+        for (index in iterable) {
+          if (callback(iterable[index], index, collection) === false) return result;
+        }
+      return result
+    };
+
+    /**
+     * This method is like `_.forIn` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * Shape.prototype.move = function(x, y) {
+     *   this.x += x;
+     *   this.y += y;
+     * };
+     *
+     * _.forInRight(new Shape, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
+     */
+    function forInRight(object, callback, thisArg) {
+      var pairs = [];
+
+      forIn(object, function(value, key) {
+        pairs.push(key, value);
+      });
+
+      var length = pairs.length;
+      callback = baseCreateCallback(callback, thisArg, 3);
+      while (length--) {
+        if (callback(pairs[length--], pairs[length], object) === false) {
+          break;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Iterates over own enumerable properties of an object, executing the callback
+     * for each property. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, key, object). Callbacks may exit iteration early by
+     * explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+     *   console.log(key);
+     * });
+     * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
+     */
+    var forOwn = function(collection, callback, thisArg) {
+      var index, iterable = collection, result = iterable;
+      if (!iterable) return result;
+      if (!objectTypes[typeof iterable]) return result;
+      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+        var ownIndex = -1,
+            ownProps = objectTypes[typeof iterable] && keys(iterable),
+            length = ownProps ? ownProps.length : 0;
+
+        while (++ownIndex < length) {
+          index = ownProps[ownIndex];
+          if (callback(iterable[index], index, collection) === false) return result;
+        }
+      return result
+    };
+
+    /**
+     * This method is like `_.forOwn` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
+     */
+    function forOwnRight(object, callback, thisArg) {
+      var props = keys(object),
+          length = props.length;
+
+      callback = baseCreateCallback(callback, thisArg, 3);
+      while (length--) {
+        var key = props[length];
+        if (callback(object[key], key, object) === false) {
+          break;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Creates a sorted array of property names of all enumerable properties,
+     * own and inherited, of `object` that have function values.
+     *
+     * @static
+     * @memberOf _
+     * @alias methods
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names that have function values.
+     * @example
+     *
+     * _.functions(_);
+     * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+     */
+    function functions(object) {
+      var result = [];
+      forIn(object, function(value, key) {
+        if (isFunction(value)) {
+          result.push(key);
+        }
+      });
+      return result.sort();
+    }
+
+    /**
+     * Checks if the specified property name exists as a direct property of `object`,
+     * instead of an inherited property.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @param {string} key The name of the property to check.
+     * @returns {boolean} Returns `true` if key is a direct property, else `false`.
+     * @example
+     *
+     * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+     * // => true
+     */
+    function has(object, key) {
+      return object ? hasOwnProperty.call(object, key) : false;
+    }
+
+    /**
+     * Creates an object composed of the inverted keys and values of the given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to invert.
+     * @returns {Object} Returns the created inverted object.
+     * @example
+     *
+     * _.invert({ 'first': 'fred', 'second': 'barney' });
+     * // => { 'fred': 'first', 'barney': 'second' }
+     */
+    function invert(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = {};
+
+      while (++index < length) {
+        var key = props[index];
+        result[object[key]] = key;
+      }
+      return result;
+    }
+
+    /**
+     * Checks if `value` is a boolean value.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
+     * @example
+     *
+     * _.isBoolean(null);
+     * // => false
+     */
+    function isBoolean(value) {
+      return value === true || value === false ||
+        value && typeof value == 'object' && toString.call(value) == boolClass || false;
+    }
+
+    /**
+     * Checks if `value` is a date.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
+     * @example
+     *
+     * _.isDate(new Date);
+     * // => true
+     */
+    function isDate(value) {
+      return value && typeof value == 'object' && toString.call(value) == dateClass || false;
+    }
+
+    /**
+     * Checks if `value` is a DOM element.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
+     * @example
+     *
+     * _.isElement(document.body);
+     * // => true
+     */
+    function isElement(value) {
+      return value && value.nodeType === 1 || false;
+    }
+
+    /**
+     * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+     * length of `0` and objects with no own enumerable properties are considered
+     * "empty".
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Array|Object|string} value The value to inspect.
+     * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
+     * @example
+     *
+     * _.isEmpty([1, 2, 3]);
+     * // => false
+     *
+     * _.isEmpty({});
+     * // => true
+     *
+     * _.isEmpty('');
+     * // => true
+     */
+    function isEmpty(value) {
+      var result = true;
+      if (!value) {
+        return result;
+      }
+      var className = toString.call(value),
+          length = value.length;
+
+      if ((className == arrayClass || className == stringClass || className == argsClass ) ||
+          (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+        return !length;
+      }
+      forOwn(value, function() {
+        return (result = false);
+      });
+      return result;
+    }
+
+    /**
+     * Performs a deep comparison between two values to determine if they are
+     * equivalent to each other. If a callback is provided it will be executed
+     * to compare values. If the callback returns `undefined` comparisons will
+     * be handled by the method instead. The callback is bound to `thisArg` and
+     * invoked with two arguments; (a, b).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} a The value to compare.
+     * @param {*} b The other value to compare.
+     * @param {Function} [callback] The function to customize comparing values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * var copy = { 'name': 'fred' };
+     *
+     * object == copy;
+     * // => false
+     *
+     * _.isEqual(object, copy);
+     * // => true
+     *
+     * var words = ['hello', 'goodbye'];
+     * var otherWords = ['hi', 'goodbye'];
+     *
+     * _.isEqual(words, otherWords, function(a, b) {
+     *   var reGreet = /^(?:hello|hi)$/i,
+     *       aGreet = _.isString(a) && reGreet.test(a),
+     *       bGreet = _.isString(b) && reGreet.test(b);
+     *
+     *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+     * });
+     * // => true
+     */
+    function isEqual(a, b, callback, thisArg) {
+      return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
+    }
+
+    /**
+     * Checks if `value` is, or can be coerced to, a finite number.
+     *
+     * Note: This is not the same as native `isFinite` which will return true for
+     * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
+     * @example
+     *
+     * _.isFinite(-101);
+     * // => true
+     *
+     * _.isFinite('10');
+     * // => true
+     *
+     * _.isFinite(true);
+     * // => false
+     *
+     * _.isFinite('');
+     * // => false
+     *
+     * _.isFinite(Infinity);
+     * // => false
+     */
+    function isFinite(value) {
+      return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+    }
+
+    /**
+     * Checks if `value` is a function.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
+     * @example
+     *
+     * _.isFunction(_);
+     * // => true
+     */
+    function isFunction(value) {
+      return typeof value == 'function';
+    }
+
+    /**
+     * Checks if `value` is the language type of Object.
+     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
+     * @example
+     *
+     * _.isObject({});
+     * // => true
+     *
+     * _.isObject([1, 2, 3]);
+     * // => true
+     *
+     * _.isObject(1);
+     * // => false
+     */
+    function isObject(value) {
+      // check if the value is the ECMAScript language type of Object
+      // http://es5.github.io/#x8
+      // and avoid a V8 bug
+      // http://code.google.com/p/v8/issues/detail?id=2291
+      return !!(value && objectTypes[typeof value]);
+    }
+
+    /**
+     * Checks if `value` is `NaN`.
+     *
+     * Note: This is not the same as native `isNaN` which will return `true` for
+     * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
+     * @example
+     *
+     * _.isNaN(NaN);
+     * // => true
+     *
+     * _.isNaN(new Number(NaN));
+     * // => true
+     *
+     * isNaN(undefined);
+     * // => true
+     *
+     * _.isNaN(undefined);
+     * // => false
+     */
+    function isNaN(value) {
+      // `NaN` as a primitive is the only value that is not equal to itself
+      // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+      return isNumber(value) && value != +value;
+    }
+
+    /**
+     * Checks if `value` is `null`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
+     * @example
+     *
+     * _.isNull(null);
+     * // => true
+     *
+     * _.isNull(undefined);
+     * // => false
+     */
+    function isNull(value) {
+      return value === null;
+    }
+
+    /**
+     * Checks if `value` is a number.
+     *
+     * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
+     * @example
+     *
+     * _.isNumber(8.4 * 5);
+     * // => true
+     */
+    function isNumber(value) {
+      return typeof value == 'number' ||
+        value && typeof value == 'object' && toString.call(value) == numberClass || false;
+    }
+
+    /**
+     * Checks if `value` is an object created by the `Object` constructor.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * _.isPlainObject(new Shape);
+     * // => false
+     *
+     * _.isPlainObject([1, 2, 3]);
+     * // => false
+     *
+     * _.isPlainObject({ 'x': 0, 'y': 0 });
+     * // => true
+     */
+    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+      if (!(value && toString.call(value) == objectClass)) {
+        return false;
+      }
+      var valueOf = value.valueOf,
+          objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+      return objProto
+        ? (value == objProto || getPrototypeOf(value) == objProto)
+        : shimIsPlainObject(value);
+    };
+
+    /**
+     * Checks if `value` is a regular expression.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
+     * @example
+     *
+     * _.isRegExp(/fred/);
+     * // => true
+     */
+    function isRegExp(value) {
+      return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
+    }
+
+    /**
+     * Checks if `value` is a string.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
+     * @example
+     *
+     * _.isString('fred');
+     * // => true
+     */
+    function isString(value) {
+      return typeof value == 'string' ||
+        value && typeof value == 'object' && toString.call(value) == stringClass || false;
+    }
+
+    /**
+     * Checks if `value` is `undefined`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
+     * @example
+     *
+     * _.isUndefined(void 0);
+     * // => true
+     */
+    function isUndefined(value) {
+      return typeof value == 'undefined';
+    }
+
+    /**
+     * Creates an object with the same keys as `object` and values generated by
+     * running each own enumerable property of `object` through the callback.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new object with values of the results of each `callback` execution.
+     * @example
+     *
+     * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     *
+     * var characters = {
+     *   'fred': { 'name': 'fred', 'age': 40 },
+     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.mapValues(characters, 'age');
+     * // => { 'fred': 40, 'pebbles': 1 }
+     */
+    function mapValues(object, callback, thisArg) {
+      var result = {};
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      forOwn(object, function(value, key, object) {
+        result[key] = callback(value, key, object);
+      });
+      return result;
+    }
+
+    /**
+     * Recursively merges own enumerable properties of the source object(s), that
+     * don't resolve to `undefined` into the destination object. Subsequent sources
+     * will overwrite property assignments of previous sources. If a callback is
+     * provided it will be executed to produce the merged values of the destination
+     * and source properties. If the callback returns `undefined` merging will
+     * be handled by the method instead. The callback is bound to `thisArg` and
+     * invoked with two arguments; (objectValue, sourceValue).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param {Function} [callback] The function to customize merging properties.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * var names = {
+     *   'characters': [
+     *     { 'name': 'barney' },
+     *     { 'name': 'fred' }
+     *   ]
+     * };
+     *
+     * var ages = {
+     *   'characters': [
+     *     { 'age': 36 },
+     *     { 'age': 40 }
+     *   ]
+     * };
+     *
+     * _.merge(names, ages);
+     * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
+     *
+     * var food = {
+     *   'fruits': ['apple'],
+     *   'vegetables': ['beet']
+     * };
+     *
+     * var otherFood = {
+     *   'fruits': ['banana'],
+     *   'vegetables': ['carrot']
+     * };
+     *
+     * _.merge(food, otherFood, function(a, b) {
+     *   return _.isArray(a) ? a.concat(b) : undefined;
+     * });
+     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+     */
+    function merge(object) {
+      var args = arguments,
+          length = 2;
+
+      if (!isObject(object)) {
+        return object;
+      }
+      // allows working with `_.reduce` and `_.reduceRight` without using
+      // their `index` and `collection` arguments
+      if (typeof args[2] != 'number') {
+        length = args.length;
+      }
+      if (length > 3 && typeof args[length - 2] == 'function') {
+        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
+      } else if (length > 2 && typeof args[length - 1] == 'function') {
+        callback = args[--length];
+      }
+      var sources = slice(arguments, 1, length),
+          index = -1,
+          stackA = getArray(),
+          stackB = getArray();
+
+      while (++index < length) {
+        baseMerge(object, sources[index], callback, stackA, stackB);
+      }
+      releaseArray(stackA);
+      releaseArray(stackB);
+      return object;
+    }
+
+    /**
+     * Creates a shallow clone of `object` excluding the specified properties.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If a callback is provided it will be executed for each
+     * property of `object` omitting the properties the callback returns truey
+     * for. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The source object.
+     * @param {Function|...string|string[]} [callback] The properties to omit or the
+     *  function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns an object without the omitted properties.
+     * @example
+     *
+     * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
+     * // => { 'name': 'fred' }
+     *
+     * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
+     *   return typeof value == 'number';
+     * });
+     * // => { 'name': 'fred' }
+     */
+    function omit(object, callback, thisArg) {
+      var result = {};
+      if (typeof callback != 'function') {
+        var props = [];
+        forIn(object, function(value, key) {
+          props.push(key);
+        });
+        props = baseDifference(props, baseFlatten(arguments, true, false, 1));
+
+        var index = -1,
+            length = props.length;
+
+        while (++index < length) {
+          var key = props[index];
+          result[key] = object[key];
+        }
+      } else {
+        callback = lodash.createCallback(callback, thisArg, 3);
+        forIn(object, function(value, key, object) {
+          if (!callback(value, key, object)) {
+            result[key] = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Creates a two dimensional array of an object's key-value pairs,
+     * i.e. `[[key1, value1], [key2, value2]]`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns new array of key-value pairs.
+     * @example
+     *
+     * _.pairs({ 'barney': 36, 'fred': 40 });
+     * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
+     */
+    function pairs(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        var key = props[index];
+        result[index] = [key, object[key]];
+      }
+      return result;
+    }
+
+    /**
+     * Creates a shallow clone of `object` composed of the specified properties.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If a callback is provided it will be executed for each
+     * property of `object` picking the properties the callback returns truey
+     * for. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The source object.
+     * @param {Function|...string|string[]} [callback] The function called per
+     *  iteration or property names to pick, specified as individual property
+     *  names or arrays of property names.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns an object composed of the picked properties.
+     * @example
+     *
+     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
+     * // => { 'name': 'fred' }
+     *
+     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
+     *   return key.charAt(0) != '_';
+     * });
+     * // => { 'name': 'fred' }
+     */
+    function pick(object, callback, thisArg) {
+      var result = {};
+      if (typeof callback != 'function') {
+        var index = -1,
+            props = baseFlatten(arguments, true, false, 1),
+            length = isObject(object) ? props.length : 0;
+
+        while (++index < length) {
+          var key = props[index];
+          if (key in object) {
+            result[key] = object[key];
+          }
+        }
+      } else {
+        callback = lodash.createCallback(callback, thisArg, 3);
+        forIn(object, function(value, key, object) {
+          if (callback(value, key, object)) {
+            result[key] = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * An alternative to `_.reduce` this method transforms `object` to a new
+     * `accumulator` object which is the result of running each of its own
+     * enumerable properties through a callback, with each callback execution
+     * potentially mutating the `accumulator` object. The callback is bound to
+     * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
+     * Callbacks may exit iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Array|Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] The custom accumulator value.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
+     *   num *= num;
+     *   if (num % 2) {
+     *     return result.push(num) < 3;
+     *   }
+     * });
+     * // => [1, 9, 25]
+     *
+     * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+     *   result[key] = num * 3;
+     * });
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     */
+    function transform(object, callback, accumulator, thisArg) {
+      var isArr = isArray(object);
+      if (accumulator == null) {
+        if (isArr) {
+          accumulator = [];
+        } else {
+          var ctor = object && object.constructor,
+              proto = ctor && ctor.prototype;
+
+          accumulator = baseCreate(proto);
+        }
+      }
+      if (callback) {
+        callback = lodash.createCallback(callback, thisArg, 4);
+        (isArr ? forEach : forOwn)(object, function(value, index, object) {
+          return callback(accumulator, value, index, object);
+        });
+      }
+      return accumulator;
+    }
+
+    /**
+     * Creates an array composed of the own enumerable property values of `object`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property values.
+     * @example
+     *
+     * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => [1, 2, 3] (property order is not guaranteed across environments)
+     */
+    function values(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = object[props[index]];
+      }
+      return result;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array of elements from the specified indexes, or keys, of the
+     * `collection`. Indexes may be specified as individual arguments or as arrays
+     * of indexes.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
+     *   to retrieve, specified as individual indexes or arrays of indexes.
+     * @returns {Array} Returns a new array of elements corresponding to the
+     *  provided indexes.
+     * @example
+     *
+     * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+     * // => ['a', 'c', 'e']
+     *
+     * _.at(['fred', 'barney', 'pebbles'], 0, 2);
+     * // => ['fred', 'pebbles']
+     */
+    function at(collection) {
+      var args = arguments,
+          index = -1,
+          props = baseFlatten(args, true, false, 1),
+          length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
+          result = Array(length);
+
+      while(++index < length) {
+        result[index] = collection[props[index]];
+      }
+      return result;
+    }
+
+    /**
+     * Checks if a given value is present in a collection using strict equality
+     * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
+     * offset from the end of the collection.
+     *
+     * @static
+     * @memberOf _
+     * @alias include
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {*} target The value to check for.
+     * @param {number} [fromIndex=0] The index to search from.
+     * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
+     * @example
+     *
+     * _.contains([1, 2, 3], 1);
+     * // => true
+     *
+     * _.contains([1, 2, 3], 1, 2);
+     * // => false
+     *
+     * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
+     * // => true
+     *
+     * _.contains('pebbles', 'eb');
+     * // => true
+     */
+    function contains(collection, target, fromIndex) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = collection ? collection.length : 0,
+          result = false;
+
+      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+      if (isArray(collection)) {
+        result = indexOf(collection, target, fromIndex) > -1;
+      } else if (typeof length == 'number') {
+        result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
+      } else {
+        forOwn(collection, function(value) {
+          if (++index >= fromIndex) {
+            return !(result = value === target);
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of `collection` through the callback. The corresponding value
+     * of each key is the number of times the key was returned by the callback.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy(['one', 'two', 'three'], 'length');
+     * // => { '3': 2, '5': 1 }
+     */
+    var countBy = createAggregator(function(result, value, key) {
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+
+    /**
+     * Checks if the given callback returns truey value for **all** elements of
+     * a collection. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias all
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if all elements passed the callback check,
+     *  else `false`.
+     * @example
+     *
+     * _.every([true, 1, null, 'yes']);
+     * // => false
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.every(characters, 'age');
+     * // => true
+     *
+     * // using "_.where" callback shorthand
+     * _.every(characters, { 'age': 36 });
+     * // => false
+     */
+    function every(collection, callback, thisArg) {
+      var result = true;
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      if (typeof length == 'number') {
+        while (++index < length) {
+          if (!(result = !!callback(collection[index], index, collection))) {
+            break;
+          }
+        }
+      } else {
+        forOwn(collection, function(value, index, collection) {
+          return (result = !!callback(value, index, collection));
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, returning an array of all elements
+     * the callback returns truey for. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias select
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of elements that passed the callback check.
+     * @example
+     *
+     * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+     * // => [2, 4, 6]
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.filter(characters, 'blocked');
+     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+     *
+     * // using "_.where" callback shorthand
+     * _.filter(characters, { 'age': 36 });
+     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+     */
+    function filter(collection, callback, thisArg) {
+      var result = [];
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      if (typeof length == 'number') {
+        while (++index < length) {
+          var value = collection[index];
+          if (callback(value, index, collection)) {
+            result.push(value);
+          }
+        }
+      } else {
+        forOwn(collection, function(value, index, collection) {
+          if (callback(value, index, collection)) {
+            result.push(value);
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, returning the first element that
+     * the callback returns truey for. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias detect, findWhere
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the found element, else `undefined`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': false },
+     *   { 'name': 'fred',    'age': 40, 'blocked': true },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+     * ];
+     *
+     * _.find(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => { 'name': 'barney', 'age': 36, 'blocked': false }
+     *
+     * // using "_.where" callback shorthand
+     * _.find(characters, { 'age': 1 });
+     * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
+     *
+     * // using "_.pluck" callback shorthand
+     * _.find(characters, 'blocked');
+     * // => { 'name': 'fred', 'age': 40, 'blocked': true }
+     */
+    function find(collection, callback, thisArg) {
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      if (typeof length == 'number') {
+        while (++index < length) {
+          var value = collection[index];
+          if (callback(value, index, collection)) {
+            return value;
+          }
+        }
+      } else {
+        var result;
+        forOwn(collection, function(value, index, collection) {
+          if (callback(value, index, collection)) {
+            result = value;
+            return false;
+          }
+        });
+        return result;
+      }
+    }
+
+    /**
+     * This method is like `_.find` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the found element, else `undefined`.
+     * @example
+     *
+     * _.findLast([1, 2, 3, 4], function(num) {
+     *   return num % 2 == 1;
+     * });
+     * // => 3
+     */
+    function findLast(collection, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forEachRight(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result = value;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, executing the callback for each
+     * element. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection). Callbacks may exit iteration early by
+     * explicitly returning `false`.
+     *
+     * Note: As with other "Collections" methods, objects with a `length` property
+     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+     * may be used for object iteration.
+     *
+     * @static
+     * @memberOf _
+     * @alias each
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
+     * // => logs each number and returns '1,2,3'
+     *
+     * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+     * // => logs each number and returns the object (property order is not guaranteed across environments)
+     */
+    function forEach(collection, callback, thisArg) {
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+      if (typeof length == 'number') {
+        while (++index < length) {
+          if (callback(collection[index], index, collection) === false) {
+            break;
+          }
+        }
+      } else {
+        forOwn(collection, callback);
+      }
+      return collection;
+    }
+
+    /**
+     * This method is like `_.forEach` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias eachRight
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
+     * // => logs each number from right to left and returns '3,2,1'
+     */
+    function forEachRight(collection, callback, thisArg) {
+      var length = collection ? collection.length : 0;
+      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+      if (typeof length == 'number') {
+        while (length--) {
+          if (callback(collection[length], length, collection) === false) {
+            break;
+          }
+        }
+      } else {
+        var props = keys(collection);
+        length = props.length;
+        forOwn(collection, function(value, key, collection) {
+          key = props ? props[--length] : --length;
+          return callback(collection[key], key, collection);
+        });
+      }
+      return collection;
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of a collection through the callback. The corresponding value
+     * of each key is an array of the elements responsible for generating the key.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * // using "_.pluck" callback shorthand
+     * _.groupBy(['one', 'two', 'three'], 'length');
+     * // => { '3': ['one', 'two'], '5': ['three'] }
+     */
+    var groupBy = createAggregator(function(result, value, key) {
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of the collection through the given callback. The corresponding
+     * value of each key is the last element responsible for generating the key.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * var keys = [
+     *   { 'dir': 'left', 'code': 97 },
+     *   { 'dir': 'right', 'code': 100 }
+     * ];
+     *
+     * _.indexBy(keys, 'dir');
+     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     */
+    var indexBy = createAggregator(function(result, value, key) {
+      result[key] = value;
+    });
+
+    /**
+     * Invokes the method named by `methodName` on each element in the `collection`
+     * returning an array of the results of each invoked method. Additional arguments
+     * will be provided to each invoked method. If `methodName` is a function it
+     * will be invoked for, and `this` bound to, each element in the `collection`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|string} methodName The name of the method to invoke or
+     *  the function invoked per iteration.
+     * @param {...*} [arg] Arguments to invoke the method with.
+     * @returns {Array} Returns a new array of the results of each invoked method.
+     * @example
+     *
+     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+     * // => [[1, 5, 7], [1, 2, 3]]
+     *
+     * _.invoke([123, 456], String.prototype.split, '');
+     * // => [['1', '2', '3'], ['4', '5', '6']]
+     */
+    function invoke(collection, methodName) {
+      var args = slice(arguments, 2),
+          index = -1,
+          isFunc = typeof methodName == 'function',
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      forEach(collection, function(value) {
+        result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+      });
+      return result;
+    }
+
+    /**
+     * Creates an array of values by running each element in the collection
+     * through the callback. The callback is bound to `thisArg` and invoked with
+     * three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias collect
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of the results of each `callback` execution.
+     * @example
+     *
+     * _.map([1, 2, 3], function(num) { return num * 3; });
+     * // => [3, 6, 9]
+     *
+     * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+     * // => [3, 6, 9] (property order is not guaranteed across environments)
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.map(characters, 'name');
+     * // => ['barney', 'fred']
+     */
+    function map(collection, callback, thisArg) {
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      if (typeof length == 'number') {
+        var result = Array(length);
+        while (++index < length) {
+          result[index] = callback(collection[index], index, collection);
+        }
+      } else {
+        result = [];
+        forOwn(collection, function(value, key, collection) {
+          result[++index] = callback(value, key, collection);
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the maximum value of a collection. If the collection is empty or
+     * falsey `-Infinity` is returned. If a callback is provided it will be executed
+     * for each value in the collection to generate the criterion by which the value
+     * is ranked. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the maximum value.
+     * @example
+     *
+     * _.max([4, 2, 8, 6]);
+     * // => 8
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.max(characters, function(chr) { return chr.age; });
+     * // => { 'name': 'fred', 'age': 40 };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.max(characters, 'age');
+     * // => { 'name': 'fred', 'age': 40 };
+     */
+    function max(collection, callback, thisArg) {
+      var computed = -Infinity,
+          result = computed;
+
+      // allows working with functions like `_.map` without using
+      // their `index` argument as a callback
+      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+        callback = null;
+      }
+      if (callback == null && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (value > result) {
+            result = value;
+          }
+        }
+      } else {
+        callback = (callback == null && isString(collection))
+          ? charAtCallback
+          : lodash.createCallback(callback, thisArg, 3);
+
+        forEach(collection, function(value, index, collection) {
+          var current = callback(value, index, collection);
+          if (current > computed) {
+            computed = current;
+            result = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the minimum value of a collection. If the collection is empty or
+     * falsey `Infinity` is returned. If a callback is provided it will be executed
+     * for each value in the collection to generate the criterion by which the value
+     * is ranked. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the minimum value.
+     * @example
+     *
+     * _.min([4, 2, 8, 6]);
+     * // => 2
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.min(characters, function(chr) { return chr.age; });
+     * // => { 'name': 'barney', 'age': 36 };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.min(characters, 'age');
+     * // => { 'name': 'barney', 'age': 36 };
+     */
+    function min(collection, callback, thisArg) {
+      var computed = Infinity,
+          result = computed;
+
+      // allows working with functions like `_.map` without using
+      // their `index` argument as a callback
+      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+        callback = null;
+      }
+      if (callback == null && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (value < result) {
+            result = value;
+          }
+        }
+      } else {
+        callback = (callback == null && isString(collection))
+          ? charAtCallback
+          : lodash.createCallback(callback, thisArg, 3);
+
+        forEach(collection, function(value, index, collection) {
+          var current = callback(value, index, collection);
+          if (current < computed) {
+            computed = current;
+            result = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the value of a specified property from all elements in the collection.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {string} property The name of the property to pluck.
+     * @returns {Array} Returns a new array of property values.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.pluck(characters, 'name');
+     * // => ['barney', 'fred']
+     */
+    var pluck = map;
+
+    /**
+     * Reduces a collection to a value which is the accumulated result of running
+     * each element in the collection through the callback, where each successive
+     * callback execution consumes the return value of the previous execution. If
+     * `accumulator` is not provided the first element of the collection will be
+     * used as the initial `accumulator` value. The callback is bound to `thisArg`
+     * and invoked with four arguments; (accumulator, value, index|key, collection).
+     *
+     * @static
+     * @memberOf _
+     * @alias foldl, inject
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] Initial value of the accumulator.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var sum = _.reduce([1, 2, 3], function(sum, num) {
+     *   return sum + num;
+     * });
+     * // => 6
+     *
+     * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+     *   result[key] = num * 3;
+     *   return result;
+     * }, {});
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     */
+    function reduce(collection, callback, accumulator, thisArg) {
+      if (!collection) return accumulator;
+      var noaccum = arguments.length < 3;
+      callback = lodash.createCallback(callback, thisArg, 4);
+
+      var index = -1,
+          length = collection.length;
+
+      if (typeof length == 'number') {
+        if (noaccum) {
+          accumulator = collection[++index];
+        }
+        while (++index < length) {
+          accumulator = callback(accumulator, collection[index], index, collection);
+        }
+      } else {
+        forOwn(collection, function(value, index, collection) {
+          accumulator = noaccum
+            ? (noaccum = false, value)
+            : callback(accumulator, value, index, collection)
+        });
+      }
+      return accumulator;
+    }
+
+    /**
+     * This method is like `_.reduce` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias foldr
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] Initial value of the accumulator.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var list = [[0, 1], [2, 3], [4, 5]];
+     * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+     * // => [4, 5, 2, 3, 0, 1]
+     */
+    function reduceRight(collection, callback, accumulator, thisArg) {
+      var noaccum = arguments.length < 3;
+      callback = lodash.createCallback(callback, thisArg, 4);
+      forEachRight(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection);
+      });
+      return accumulator;
+    }
+
+    /**
+     * The opposite of `_.filter` this method returns the elements of a
+     * collection that the callback does **not** return truey for.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of elements that failed the callback check.
+     * @example
+     *
+     * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+     * // => [1, 3, 5]
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.reject(characters, 'blocked');
+     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+     *
+     * // using "_.where" callback shorthand
+     * _.reject(characters, { 'age': 36 });
+     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+     */
+    function reject(collection, callback, thisArg) {
+      callback = lodash.createCallback(callback, thisArg, 3);
+      return filter(collection, function(value, index, collection) {
+        return !callback(value, index, collection);
+      });
+    }
+
+    /**
+     * Retrieves a random element or `n` random elements from a collection.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to sample.
+     * @param {number} [n] The number of elements to sample.
+     * @param- {Object} [guard] Allows working with functions like `_.map`
+     *  without using their `index` arguments as `n`.
+     * @returns {Array} Returns the random sample(s) of `collection`.
+     * @example
+     *
+     * _.sample([1, 2, 3, 4]);
+     * // => 2
+     *
+     * _.sample([1, 2, 3, 4], 2);
+     * // => [3, 1]
+     */
+    function sample(collection, n, guard) {
+      if (collection && typeof collection.length != 'number') {
+        collection = values(collection);
+      }
+      if (n == null || guard) {
+        return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
+      }
+      var result = shuffle(collection);
+      result.length = nativeMin(nativeMax(0, n), result.length);
+      return result;
+    }
+
+    /**
+     * Creates an array of shuffled values, using a version of the Fisher-Yates
+     * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to shuffle.
+     * @returns {Array} Returns a new shuffled collection.
+     * @example
+     *
+     * _.shuffle([1, 2, 3, 4, 5, 6]);
+     * // => [4, 1, 6, 3, 5, 2]
+     */
+    function shuffle(collection) {
+      var index = -1,
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      forEach(collection, function(value) {
+        var rand = baseRandom(0, ++index);
+        result[index] = result[rand];
+        result[rand] = value;
+      });
+      return result;
+    }
+
+    /**
+     * Gets the size of the `collection` by returning `collection.length` for arrays
+     * and array-like objects or the number of own enumerable properties for objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to inspect.
+     * @returns {number} Returns `collection.length` or number of own enumerable properties.
+     * @example
+     *
+     * _.size([1, 2]);
+     * // => 2
+     *
+     * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => 3
+     *
+     * _.size('pebbles');
+     * // => 7
+     */
+    function size(collection) {
+      var length = collection ? collection.length : 0;
+      return typeof length == 'number' ? length : keys(collection).length;
+    }
+
+    /**
+     * Checks if the callback returns a truey value for **any** element of a
+     * collection. The function returns as soon as it finds a passing value and
+     * does not iterate over the entire collection. The callback is bound to
+     * `thisArg` and invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias any
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if any element passed the callback check,
+     *  else `false`.
+     * @example
+     *
+     * _.some([null, 0, 'yes', false], Boolean);
+     * // => true
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.some(characters, 'blocked');
+     * // => true
+     *
+     * // using "_.where" callback shorthand
+     * _.some(characters, { 'age': 1 });
+     * // => false
+     */
+    function some(collection, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      if (typeof length == 'number') {
+        while (++index < length) {
+          if ((result = callback(collection[index], index, collection))) {
+            break;
+          }
+        }
+      } else {
+        forOwn(collection, function(value, index, collection) {
+          return !(result = callback(value, index, collection));
+        });
+      }
+      return !!result;
+    }
+
+    /**
+     * Creates an array of elements, sorted in ascending order by the results of
+     * running each element in a collection through the callback. This method
+     * performs a stable sort, that is, it will preserve the original sort order
+     * of equal elements. The callback is bound to `thisArg` and invoked with
+     * three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an array of property names is provided for `callback` the collection
+     * will be sorted by each property value.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Array|Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of sorted elements.
+     * @example
+     *
+     * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+     * // => [3, 1, 2]
+     *
+     * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+     * // => [3, 1, 2]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36 },
+     *   { 'name': 'fred',    'age': 40 },
+     *   { 'name': 'barney',  'age': 26 },
+     *   { 'name': 'fred',    'age': 30 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.map(_.sortBy(characters, 'age'), _.values);
+     * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
+     *
+     * // sorting by multiple properties
+     * _.map(_.sortBy(characters, ['name', 'age']), _.values);
+     * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
+     */
+    function sortBy(collection, callback, thisArg) {
+      var index = -1,
+          isArr = isArray(callback),
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      if (!isArr) {
+        callback = lodash.createCallback(callback, thisArg, 3);
+      }
+      forEach(collection, function(value, key, collection) {
+        var object = result[++index] = getObject();
+        if (isArr) {
+          object.criteria = map(callback, function(key) { return value[key]; });
+        } else {
+          (object.criteria = getArray())[0] = callback(value, key, collection);
+        }
+        object.index = index;
+        object.value = value;
+      });
+
+      length = result.length;
+      result.sort(compareAscending);
+      while (length--) {
+        var object = result[length];
+        result[length] = object.value;
+        if (!isArr) {
+          releaseArray(object.criteria);
+        }
+        releaseObject(object);
+      }
+      return result;
+    }
+
+    /**
+     * Converts the `collection` to an array.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to convert.
+     * @returns {Array} Returns the new converted array.
+     * @example
+     *
+     * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+     * // => [2, 3, 4]
+     */
+    function toArray(collection) {
+      if (collection && typeof collection.length == 'number') {
+        return slice(collection);
+      }
+      return values(collection);
+    }
+
+    /**
+     * Performs a deep comparison of each element in a `collection` to the given
+     * `properties` object, returning an array of all elements that have equivalent
+     * property values.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Object} props The object of property values to filter by.
+     * @returns {Array} Returns a new array of elements that have the given properties.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
+     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * _.where(characters, { 'age': 36 });
+     * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
+     *
+     * _.where(characters, { 'pets': ['dino'] });
+     * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
+     */
+    var where = filter;
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array with all falsey values removed. The values `false`, `null`,
+     * `0`, `""`, `undefined`, and `NaN` are all falsey.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to compact.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.compact([0, 1, false, 2, '', 3]);
+     * // => [1, 2, 3]
+     */
+    function compact(array) {
+      var index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+        if (value) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array excluding all values of the provided arrays using strict
+     * equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to process.
+     * @param {...Array} [values] The arrays of values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+     * // => [1, 3, 4]
+     */
+    function difference(array) {
+      return baseDifference(array, baseFlatten(arguments, true, true, 1));
+    }
+
+    /**
+     * This method is like `_.find` except that it returns the index of the first
+     * element that passes the callback check, instead of the element itself.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': false },
+     *   { 'name': 'fred',    'age': 40, 'blocked': true },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+     * ];
+     *
+     * _.findIndex(characters, function(chr) {
+     *   return chr.age < 20;
+     * });
+     * // => 2
+     *
+     * // using "_.where" callback shorthand
+     * _.findIndex(characters, { 'age': 36 });
+     * // => 0
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findIndex(characters, 'blocked');
+     * // => 1
+     */
+    function findIndex(array, callback, thisArg) {
+      var index = -1,
+          length = array ? array.length : 0;
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (++index < length) {
+        if (callback(array[index], index, array)) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * This method is like `_.findIndex` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': true },
+     *   { 'name': 'fred',    'age': 40, 'blocked': false },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
+     * ];
+     *
+     * _.findLastIndex(characters, function(chr) {
+     *   return chr.age > 30;
+     * });
+     * // => 1
+     *
+     * // using "_.where" callback shorthand
+     * _.findLastIndex(characters, { 'age': 36 });
+     * // => 0
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findLastIndex(characters, 'blocked');
+     * // => 2
+     */
+    function findLastIndex(array, callback, thisArg) {
+      var length = array ? array.length : 0;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (length--) {
+        if (callback(array[length], length, array)) {
+          return length;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Gets the first element or first `n` elements of an array. If a callback
+     * is provided elements at the beginning of the array are returned as long
+     * as the callback returns truey. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias head, take
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback] The function called
+     *  per element or the number of elements to return. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the first element(s) of `array`.
+     * @example
+     *
+     * _.first([1, 2, 3]);
+     * // => 1
+     *
+     * _.first([1, 2, 3], 2);
+     * // => [1, 2]
+     *
+     * _.first([1, 2, 3], function(num) {
+     *   return num < 3;
+     * });
+     * // => [1, 2]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.first(characters, 'blocked');
+     * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
+     *
+     * // using "_.where" callback shorthand
+     * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
+     * // => ['barney', 'fred']
+     */
+    function first(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array ? array[0] : undefined;
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+
+    /**
+     * Flattens a nested array (the nesting can be to any depth). If `isShallow`
+     * is truey, the array will only be flattened a single level. If a callback
+     * is provided each element of the array is passed through the callback before
+     * flattening. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new flattened array.
+     * @example
+     *
+     * _.flatten([1, [2], [3, [[4]]]]);
+     * // => [1, 2, 3, 4];
+     *
+     * _.flatten([1, [2], [3, [[4]]]], true);
+     * // => [1, 2, 3, [[4]]];
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
+     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.flatten(characters, 'pets');
+     * // => ['hoppy', 'baby puss', 'dino']
+     */
+    function flatten(array, isShallow, callback, thisArg) {
+      // juggle arguments
+      if (typeof isShallow != 'boolean' && isShallow != null) {
+        thisArg = callback;
+        callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
+        isShallow = false;
+      }
+      if (callback != null) {
+        array = map(array, callback, thisArg);
+      }
+      return baseFlatten(array, isShallow);
+    }
+
+    /**
+     * Gets the index at which the first occurrence of `value` is found using
+     * strict equality for comparisons, i.e. `===`. If the array is already sorted
+     * providing `true` for `fromIndex` will run a faster binary search.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+     *  to perform a binary search on a sorted array.
+     * @returns {number} Returns the index of the matched value or `-1`.
+     * @example
+     *
+     * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+     * // => 1
+     *
+     * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+     * // => 4
+     *
+     * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+     * // => 2
+     */
+    function indexOf(array, value, fromIndex) {
+      if (typeof fromIndex == 'number') {
+        var length = array ? array.length : 0;
+        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
+      } else if (fromIndex) {
+        var index = sortedIndex(array, value);
+        return array[index] === value ? index : -1;
+      }
+      return baseIndexOf(array, value, fromIndex);
+    }
+
+    /**
+     * Gets all but the last element or last `n` elements of an array. If a
+     * callback is provided elements at the end of the array are excluded from
+     * the result as long as the callback returns truey. The callback is bound
+     * to `thisArg` and invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback=1] The function called
+     *  per element or the number of elements to exclude. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a slice of `array`.
+     * @example
+     *
+     * _.initial([1, 2, 3]);
+     * // => [1, 2]
+     *
+     * _.initial([1, 2, 3], 2);
+     * // => [1]
+     *
+     * _.initial([1, 2, 3], function(num) {
+     *   return num > 1;
+     * });
+     * // => [1]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.initial(characters, 'blocked');
+     * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
+     *
+     * // using "_.where" callback shorthand
+     * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
+     * // => ['barney', 'fred']
+     */
+    function initial(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = (callback == null || thisArg) ? 1 : callback || n;
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+    }
+
+    /**
+     * Creates an array of unique values present in all provided arrays using
+     * strict equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of shared values.
+     * @example
+     *
+     * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+     * // => [1, 2]
+     */
+    function intersection() {
+      var args = [],
+          argsIndex = -1,
+          argsLength = arguments.length,
+          caches = getArray(),
+          indexOf = getIndexOf(),
+          trustIndexOf = indexOf === baseIndexOf,
+          seen = getArray();
+
+      while (++argsIndex < argsLength) {
+        var value = arguments[argsIndex];
+        if (isArray(value) || isArguments(value)) {
+          args.push(value);
+          caches.push(trustIndexOf && value.length >= largeArraySize &&
+            createCache(argsIndex ? args[argsIndex] : seen));
+        }
+      }
+      var array = args[0],
+          index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      outer:
+      while (++index < length) {
+        var cache = caches[0];
+        value = array[index];
+
+        if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
+          argsIndex = argsLength;
+          (cache || seen).push(value);
+          while (--argsIndex) {
+            cache = caches[argsIndex];
+            if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
+              continue outer;
+            }
+          }
+          result.push(value);
+        }
+      }
+      while (argsLength--) {
+        cache = caches[argsLength];
+        if (cache) {
+          releaseObject(cache);
+        }
+      }
+      releaseArray(caches);
+      releaseArray(seen);
+      return result;
+    }
+
+    /**
+     * Gets the last element or last `n` elements of an array. If a callback is
+     * provided elements at the end of the array are returned as long as the
+     * callback returns truey. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback] The function called
+     *  per element or the number of elements to return. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the last element(s) of `array`.
+     * @example
+     *
+     * _.last([1, 2, 3]);
+     * // => 3
+     *
+     * _.last([1, 2, 3], 2);
+     * // => [2, 3]
+     *
+     * _.last([1, 2, 3], function(num) {
+     *   return num > 1;
+     * });
+     * // => [2, 3]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.pluck(_.last(characters, 'blocked'), 'name');
+     * // => ['fred', 'pebbles']
+     *
+     * // using "_.where" callback shorthand
+     * _.last(characters, { 'employer': 'na' });
+     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+     */
+    function last(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array ? array[length - 1] : undefined;
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+
+    /**
+     * Gets the index at which the last occurrence of `value` is found using strict
+     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+     * as the offset from the end of the collection.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {number} [fromIndex=array.length-1] The index to search from.
+     * @returns {number} Returns the index of the matched value or `-1`.
+     * @example
+     *
+     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+     * // => 4
+     *
+     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+     * // => 1
+     */
+    function lastIndexOf(array, value, fromIndex) {
+      var index = array ? array.length : 0;
+      if (typeof fromIndex == 'number') {
+        index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+      }
+      while (index--) {
+        if (array[index] === value) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Removes all provided values from the given array using strict equality for
+     * comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to modify.
+     * @param {...*} [value] The values to remove.
+     * @returns {Array} Returns `array`.
+     * @example
+     *
+     * var array = [1, 2, 3, 1, 2, 3];
+     * _.pull(array, 2, 3);
+     * console.log(array);
+     * // => [1, 1]
+     */
+    function pull(array) {
+      var args = arguments,
+          argsIndex = 0,
+          argsLength = args.length,
+          length = array ? array.length : 0;
+
+      while (++argsIndex < argsLength) {
+        var index = -1,
+            value = args[argsIndex];
+        while (++index < length) {
+          if (array[index] === value) {
+            splice.call(array, index--, 1);
+            length--;
+          }
+        }
+      }
+      return array;
+    }
+
+    /**
+     * Creates an array of numbers (positive and/or negative) progressing from
+     * `start` up to but not including `end`. If `start` is less than `stop` a
+     * zero-length range is created unless a negative `step` is specified.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {number} [start=0] The start of the range.
+     * @param {number} end The end of the range.
+     * @param {number} [step=1] The value to increment or decrement by.
+     * @returns {Array} Returns a new range array.
+     * @example
+     *
+     * _.range(4);
+     * // => [0, 1, 2, 3]
+     *
+     * _.range(1, 5);
+     * // => [1, 2, 3, 4]
+     *
+     * _.range(0, 20, 5);
+     * // => [0, 5, 10, 15]
+     *
+     * _.range(0, -4, -1);
+     * // => [0, -1, -2, -3]
+     *
+     * _.range(1, 4, 0);
+     * // => [1, 1, 1]
+     *
+     * _.range(0);
+     * // => []
+     */
+    function range(start, end, step) {
+      start = +start || 0;
+      step = typeof step == 'number' ? step : (+step || 1);
+
+      if (end == null) {
+        end = start;
+        start = 0;
+      }
+      // use `Array(length)` so engines like Chakra and V8 avoid slower modes
+      // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+      var index = -1,
+          length = nativeMax(0, ceil((end - start) / (step || 1))),
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = start;
+        start += step;
+      }
+      return result;
+    }
+
+    /**
+     * Removes all elements from an array that the callback returns truey for
+     * and returns an array of removed elements. The callback is bound to `thisArg`
+     * and invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to modify.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of removed elements.
+     * @example
+     *
+     * var array = [1, 2, 3, 4, 5, 6];
+     * var evens = _.remove(array, function(num) { return num % 2 == 0; });
+     *
+     * console.log(array);
+     * // => [1, 3, 5]
+     *
+     * console.log(evens);
+     * // => [2, 4, 6]
+     */
+    function remove(array, callback, thisArg) {
+      var index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (++index < length) {
+        var value = array[index];
+        if (callback(value, index, array)) {
+          result.push(value);
+          splice.call(array, index--, 1);
+          length--;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The opposite of `_.initial` this method gets all but the first element or
+     * first `n` elements of an array. If a callback function is provided elements
+     * at the beginning of the array are excluded from the result as long as the
+     * callback returns truey. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias drop, tail
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback=1] The function called
+     *  per element or the number of elements to exclude. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a slice of `array`.
+     * @example
+     *
+     * _.rest([1, 2, 3]);
+     * // => [2, 3]
+     *
+     * _.rest([1, 2, 3], 2);
+     * // => [3]
+     *
+     * _.rest([1, 2, 3], function(num) {
+     *   return num < 3;
+     * });
+     * // => [3]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.pluck(_.rest(characters, 'blocked'), 'name');
+     * // => ['fred', 'pebbles']
+     *
+     * // using "_.where" callback shorthand
+     * _.rest(characters, { 'employer': 'slate' });
+     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+     */
+    function rest(array, callback, thisArg) {
+      if (typeof callback != 'number' && callback != null) {
+        var n = 0,
+            index = -1,
+            length = array ? array.length : 0;
+
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+      }
+      return slice(array, n);
+    }
+
+    /**
+     * Uses a binary search to determine the smallest index at which a value
+     * should be inserted into a given sorted array in order to maintain the sort
+     * order of the array. If a callback is provided it will be executed for
+     * `value` and each element of `array` to compute their sort ranking. The
+     * callback is bound to `thisArg` and invoked with one argument; (value).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     * @example
+     *
+     * _.sortedIndex([20, 30, 50], 40);
+     * // => 2
+     *
+     * // using "_.pluck" callback shorthand
+     * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+     * // => 2
+     *
+     * var dict = {
+     *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+     * };
+     *
+     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+     *   return dict.wordToNumber[word];
+     * });
+     * // => 2
+     *
+     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+     *   return this.wordToNumber[word];
+     * }, dict);
+     * // => 2
+     */
+    function sortedIndex(array, value, callback, thisArg) {
+      var low = 0,
+          high = array ? array.length : low;
+
+      // explicitly reference `identity` for better inlining in Firefox
+      callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
+      value = callback(value);
+
+      while (low < high) {
+        var mid = (low + high) >>> 1;
+        (callback(array[mid]) < value)
+          ? low = mid + 1
+          : high = mid;
+      }
+      return low;
+    }
+
+    /**
+     * Creates an array of unique values, in order, of the provided arrays using
+     * strict equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of combined values.
+     * @example
+     *
+     * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+     * // => [1, 2, 3, 5, 4]
+     */
+    function union() {
+      return baseUniq(baseFlatten(arguments, true, true));
+    }
+
+    /**
+     * Creates a duplicate-value-free version of an array using strict equality
+     * for comparisons, i.e. `===`. If the array is sorted, providing
+     * `true` for `isSorted` will use a faster algorithm. If a callback is provided
+     * each element of `array` is passed through the callback before uniqueness
+     * is computed. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias unique
+     * @category Arrays
+     * @param {Array} array The array to process.
+     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a duplicate-value-free array.
+     * @example
+     *
+     * _.uniq([1, 2, 1, 3, 1]);
+     * // => [1, 2, 3]
+     *
+     * _.uniq([1, 1, 2, 2, 3], true);
+     * // => [1, 2, 3]
+     *
+     * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
+     * // => ['A', 'b', 'C']
+     *
+     * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+     * // => [1, 2.5, 3]
+     *
+     * // using "_.pluck" callback shorthand
+     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+     * // => [{ 'x': 1 }, { 'x': 2 }]
+     */
+    function uniq(array, isSorted, callback, thisArg) {
+      // juggle arguments
+      if (typeof isSorted != 'boolean' && isSorted != null) {
+        thisArg = callback;
+        callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
+        isSorted = false;
+      }
+      if (callback != null) {
+        callback = lodash.createCallback(callback, thisArg, 3);
+      }
+      return baseUniq(array, isSorted, callback);
+    }
+
+    /**
+     * Creates an array excluding all provided values using strict equality for
+     * comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to filter.
+     * @param {...*} [value] The values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+     * // => [2, 3, 4]
+     */
+    function without(array) {
+      return baseDifference(array, slice(arguments, 1));
+    }
+
+    /**
+     * Creates an array that is the symmetric difference of the provided arrays.
+     * See http://en.wikipedia.org/wiki/Symmetric_difference.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of values.
+     * @example
+     *
+     * _.xor([1, 2, 3], [5, 2, 1, 4]);
+     * // => [3, 5, 4]
+     *
+     * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
+     * // => [1, 4, 5]
+     */
+    function xor() {
+      var index = -1,
+          length = arguments.length;
+
+      while (++index < length) {
+        var array = arguments[index];
+        if (isArray(array) || isArguments(array)) {
+          var result = result
+            ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
+            : array;
+        }
+      }
+      return result || [];
+    }
+
+    /**
+     * Creates an array of grouped elements, the first of which contains the first
+     * elements of the given arrays, the second of which contains the second
+     * elements of the given arrays, and so on.
+     *
+     * @static
+     * @memberOf _
+     * @alias unzip
+     * @category Arrays
+     * @param {...Array} [array] Arrays to process.
+     * @returns {Array} Returns a new array of grouped elements.
+     * @example
+     *
+     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+     * // => [['fred', 30, true], ['barney', 40, false]]
+     */
+    function zip() {
+      var array = arguments.length > 1 ? arguments : arguments[0],
+          index = -1,
+          length = array ? max(pluck(array, 'length')) : 0,
+          result = Array(length < 0 ? 0 : length);
+
+      while (++index < length) {
+        result[index] = pluck(array, index);
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed from arrays of `keys` and `values`. Provide
+     * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
+     * or two arrays, one of `keys` and one of corresponding `values`.
+     *
+     * @static
+     * @memberOf _
+     * @alias object
+     * @category Arrays
+     * @param {Array} keys The array of keys.
+     * @param {Array} [values=[]] The array of values.
+     * @returns {Object} Returns an object composed of the given keys and
+     *  corresponding values.
+     * @example
+     *
+     * _.zipObject(['fred', 'barney'], [30, 40]);
+     * // => { 'fred': 30, 'barney': 40 }
+     */
+    function zipObject(keys, values) {
+      var index = -1,
+          length = keys ? keys.length : 0,
+          result = {};
+
+      if (!values && length && !isArray(keys[0])) {
+        values = [];
+      }
+      while (++index < length) {
+        var key = keys[index];
+        if (values) {
+          result[key] = values[index];
+        } else if (key) {
+          result[key[0]] = key[1];
+        }
+      }
+      return result;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a function that executes `func`, with  the `this` binding and
+     * arguments of the created function, only after being called `n` times.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {number} n The number of times the function must be called before
+     *  `func` is executed.
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var saves = ['profile', 'settings'];
+     *
+     * var done = _.after(saves.length, function() {
+     *   console.log('Done saving!');
+     * });
+     *
+     * _.forEach(saves, function(type) {
+     *   asyncSave({ 'type': type, 'complete': done });
+     * });
+     * // => logs 'Done saving!', after all saves have completed
+     */
+    function after(n, func) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      return function() {
+        if (--n < 1) {
+          return func.apply(this, arguments);
+        }
+      };
+    }
+
+    /**
+     * Creates a function that, when called, invokes `func` with the `this`
+     * binding of `thisArg` and prepends any additional `bind` arguments to those
+     * provided to the bound function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to bind.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var func = function(greeting) {
+     *   return greeting + ' ' + this.name;
+     * };
+     *
+     * func = _.bind(func, { 'name': 'fred' }, 'hi');
+     * func();
+     * // => 'hi fred'
+     */
+    function bind(func, thisArg) {
+      return arguments.length > 2
+        ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
+        : createWrapper(func, 1, null, null, thisArg);
+    }
+
+    /**
+     * Binds methods of an object to the object itself, overwriting the existing
+     * method. Method names may be specified as individual arguments or as arrays
+     * of method names. If no method names are provided all the function properties
+     * of `object` will be bound.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Object} object The object to bind and assign the bound methods to.
+     * @param {...string} [methodName] The object method names to
+     *  bind, specified as individual method names or arrays of method names.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'onClick': function() { console.log('clicked ' + this.label); }
+     * };
+     *
+     * _.bindAll(view);
+     * jQuery('#docs').on('click', view.onClick);
+     * // => logs 'clicked docs', when the button is clicked
+     */
+    function bindAll(object) {
+      var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
+          index = -1,
+          length = funcs.length;
+
+      while (++index < length) {
+        var key = funcs[index];
+        object[key] = createWrapper(object[key], 1, null, null, object);
+      }
+      return object;
+    }
+
+    /**
+     * Creates a function that, when called, invokes the method at `object[key]`
+     * and prepends any additional `bindKey` arguments to those provided to the bound
+     * function. This method differs from `_.bind` by allowing bound functions to
+     * reference methods that will be redefined or don't yet exist.
+     * See http://michaux.ca/articles/lazy-function-definition-pattern.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Object} object The object the method belongs to.
+     * @param {string} key The key of the method.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var object = {
+     *   'name': 'fred',
+     *   'greet': function(greeting) {
+     *     return greeting + ' ' + this.name;
+     *   }
+     * };
+     *
+     * var func = _.bindKey(object, 'greet', 'hi');
+     * func();
+     * // => 'hi fred'
+     *
+     * object.greet = function(greeting) {
+     *   return greeting + 'ya ' + this.name + '!';
+     * };
+     *
+     * func();
+     * // => 'hiya fred!'
+     */
+    function bindKey(object, key) {
+      return arguments.length > 2
+        ? createWrapper(key, 19, slice(arguments, 2), null, object)
+        : createWrapper(key, 3, null, null, object);
+    }
+
+    /**
+     * Creates a function that is the composition of the provided functions,
+     * where each function consumes the return value of the function that follows.
+     * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+     * Each function is executed with the `this` binding of the composed function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {...Function} [func] Functions to compose.
+     * @returns {Function} Returns the new composed function.
+     * @example
+     *
+     * var realNameMap = {
+     *   'pebbles': 'penelope'
+     * };
+     *
+     * var format = function(name) {
+     *   name = realNameMap[name.toLowerCase()] || name;
+     *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
+     * };
+     *
+     * var greet = function(formatted) {
+     *   return 'Hiya ' + formatted + '!';
+     * };
+     *
+     * var welcome = _.compose(greet, format);
+     * welcome('pebbles');
+     * // => 'Hiya Penelope!'
+     */
+    function compose() {
+      var funcs = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        if (!isFunction(funcs[length])) {
+          throw new TypeError;
+        }
+      }
+      return function() {
+        var args = arguments,
+            length = funcs.length;
+
+        while (length--) {
+          args = [funcs[length].apply(this, args)];
+        }
+        return args[0];
+      };
+    }
+
+    /**
+     * Creates a function which accepts one or more arguments of `func` that when
+     * invoked either executes `func` returning its result, if all `func` arguments
+     * have been provided, or returns a function that accepts one or more of the
+     * remaining `func` arguments, and so on. The arity of `func` can be specified
+     * if `func.length` is not sufficient.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to curry.
+     * @param {number} [arity=func.length] The arity of `func`.
+     * @returns {Function} Returns the new curried function.
+     * @example
+     *
+     * var curried = _.curry(function(a, b, c) {
+     *   console.log(a + b + c);
+     * });
+     *
+     * curried(1)(2)(3);
+     * // => 6
+     *
+     * curried(1, 2)(3);
+     * // => 6
+     *
+     * curried(1, 2, 3);
+     * // => 6
+     */
+    function curry(func, arity) {
+      arity = typeof arity == 'number' ? arity : (+arity || func.length);
+      return createWrapper(func, 4, null, null, null, arity);
+    }
+
+    /**
+     * Creates a function that will delay the execution of `func` until after
+     * `wait` milliseconds have elapsed since the last time it was invoked.
+     * Provide an options object to indicate that `func` should be invoked on
+     * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
+     * to the debounced function will return the result of the last `func` call.
+     *
+     * Note: If `leading` and `trailing` options are `true` `func` will be called
+     * on the trailing edge of the timeout only if the the debounced function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to debounce.
+     * @param {number} wait The number of milliseconds to delay.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
+     * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
+     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+     * @returns {Function} Returns the new debounced function.
+     * @example
+     *
+     * // avoid costly calculations while the window size is in flux
+     * var lazyLayout = _.debounce(calculateLayout, 150);
+     * jQuery(window).on('resize', lazyLayout);
+     *
+     * // execute `sendMail` when the click event is fired, debouncing subsequent calls
+     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+     *   'leading': true,
+     *   'trailing': false
+     * });
+     *
+     * // ensure `batchLog` is executed once after 1 second of debounced calls
+     * var source = new EventSource('/stream');
+     * source.addEventListener('message', _.debounce(batchLog, 250, {
+     *   'maxWait': 1000
+     * }, false);
+     */
+    function debounce(func, wait, options) {
+      var args,
+          maxTimeoutId,
+          result,
+          stamp,
+          thisArg,
+          timeoutId,
+          trailingCall,
+          lastCalled = 0,
+          maxWait = false,
+          trailing = true;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      wait = nativeMax(0, wait) || 0;
+      if (options === true) {
+        var leading = true;
+        trailing = false;
+      } else if (isObject(options)) {
+        leading = options.leading;
+        maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+      var delayed = function() {
+        var remaining = wait - (now() - stamp);
+        if (remaining <= 0) {
+          if (maxTimeoutId) {
+            clearTimeout(maxTimeoutId);
+          }
+          var isCalled = trailingCall;
+          maxTimeoutId = timeoutId = trailingCall = undefined;
+          if (isCalled) {
+            lastCalled = now();
+            result = func.apply(thisArg, args);
+            if (!timeoutId && !maxTimeoutId) {
+              args = thisArg = null;
+            }
+          }
+        } else {
+          timeoutId = setTimeout(delayed, remaining);
+        }
+      };
+
+      var maxDelayed = function() {
+        if (timeoutId) {
+          clearTimeout(timeoutId);
+        }
+        maxTimeoutId = timeoutId = trailingCall = undefined;
+        if (trailing || (maxWait !== wait)) {
+          lastCalled = now();
+          result = func.apply(thisArg, args);
+          if (!timeoutId && !maxTimeoutId) {
+            args = thisArg = null;
+          }
+        }
+      };
+
+      return function() {
+        args = arguments;
+        stamp = now();
+        thisArg = this;
+        trailingCall = trailing && (timeoutId || !leading);
+
+        if (maxWait === false) {
+          var leadingCall = leading && !timeoutId;
+        } else {
+          if (!maxTimeoutId && !leading) {
+            lastCalled = stamp;
+          }
+          var remaining = maxWait - (stamp - lastCalled),
+              isCalled = remaining <= 0;
+
+          if (isCalled) {
+            if (maxTimeoutId) {
+              maxTimeoutId = clearTimeout(maxTimeoutId);
+            }
+            lastCalled = stamp;
+            result = func.apply(thisArg, args);
+          }
+          else if (!maxTimeoutId) {
+            maxTimeoutId = setTimeout(maxDelayed, remaining);
+          }
+        }
+        if (isCalled && timeoutId) {
+          timeoutId = clearTimeout(timeoutId);
+        }
+        else if (!timeoutId && wait !== maxWait) {
+          timeoutId = setTimeout(delayed, wait);
+        }
+        if (leadingCall) {
+          isCalled = true;
+          result = func.apply(thisArg, args);
+        }
+        if (isCalled && !timeoutId && !maxTimeoutId) {
+          args = thisArg = null;
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Defers executing the `func` function until the current call stack has cleared.
+     * Additional arguments will be provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to defer.
+     * @param {...*} [arg] Arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.defer(function(text) { console.log(text); }, 'deferred');
+     * // logs 'deferred' after one or more milliseconds
+     */
+    function defer(func) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var args = slice(arguments, 1);
+      return setTimeout(function() { func.apply(undefined, args); }, 1);
+    }
+
+    /**
+     * Executes the `func` function after `wait` milliseconds. Additional arguments
+     * will be provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to delay.
+     * @param {number} wait The number of milliseconds to delay execution.
+     * @param {...*} [arg] Arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.delay(function(text) { console.log(text); }, 1000, 'later');
+     * // => logs 'later' after one second
+     */
+    function delay(func, wait) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var args = slice(arguments, 2);
+      return setTimeout(function() { func.apply(undefined, args); }, wait);
+    }
+
+    /**
+     * Creates a function that memoizes the result of `func`. If `resolver` is
+     * provided it will be used to determine the cache key for storing the result
+     * based on the arguments provided to the memoized function. By default, the
+     * first argument provided to the memoized function is used as the cache key.
+     * The `func` is executed with the `this` binding of the memoized function.
+     * The result cache is exposed as the `cache` property on the memoized function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to have its output memoized.
+     * @param {Function} [resolver] A function used to resolve the cache key.
+     * @returns {Function} Returns the new memoizing function.
+     * @example
+     *
+     * var fibonacci = _.memoize(function(n) {
+     *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+     * });
+     *
+     * fibonacci(9)
+     * // => 34
+     *
+     * var data = {
+     *   'fred': { 'name': 'fred', 'age': 40 },
+     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // modifying the result cache
+     * var get = _.memoize(function(name) { return data[name]; }, _.identity);
+     * get('pebbles');
+     * // => { 'name': 'pebbles', 'age': 1 }
+     *
+     * get.cache.pebbles.name = 'penelope';
+     * get('pebbles');
+     * // => { 'name': 'penelope', 'age': 1 }
+     */
+    function memoize(func, resolver) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var memoized = function() {
+        var cache = memoized.cache,
+            key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
+
+        return hasOwnProperty.call(cache, key)
+          ? cache[key]
+          : (cache[key] = func.apply(this, arguments));
+      }
+      memoized.cache = {};
+      return memoized;
+    }
+
+    /**
+     * Creates a function that is restricted to execute `func` once. Repeat calls to
+     * the function will return the value of the first call. The `func` is executed
+     * with the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var initialize = _.once(createApplication);
+     * initialize();
+     * initialize();
+     * // `initialize` executes `createApplication` once
+     */
+    function once(func) {
+      var ran,
+          result;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      return function() {
+        if (ran) {
+          return result;
+        }
+        ran = true;
+        result = func.apply(this, arguments);
+
+        // clear the `func` variable so the function may be garbage collected
+        func = null;
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that, when called, invokes `func` with any additional
+     * `partial` arguments prepended to those provided to the new function. This
+     * method is similar to `_.bind` except it does **not** alter the `this` binding.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var greet = function(greeting, name) { return greeting + ' ' + name; };
+     * var hi = _.partial(greet, 'hi');
+     * hi('fred');
+     * // => 'hi fred'
+     */
+    function partial(func) {
+      return createWrapper(func, 16, slice(arguments, 1));
+    }
+
+    /**
+     * This method is like `_.partial` except that `partial` arguments are
+     * appended to those provided to the new function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var defaultsDeep = _.partialRight(_.merge, _.defaults);
+     *
+     * var options = {
+     *   'variable': 'data',
+     *   'imports': { 'jq': $ }
+     * };
+     *
+     * defaultsDeep(options, _.templateSettings);
+     *
+     * options.variable
+     * // => 'data'
+     *
+     * options.imports
+     * // => { '_': _, 'jq': $ }
+     */
+    function partialRight(func) {
+      return createWrapper(func, 32, null, slice(arguments, 1));
+    }
+
+    /**
+     * Creates a function that, when executed, will only call the `func` function
+     * at most once per every `wait` milliseconds. Provide an options object to
+     * indicate that `func` should be invoked on the leading and/or trailing edge
+     * of the `wait` timeout. Subsequent calls to the throttled function will
+     * return the result of the last `func` call.
+     *
+     * Note: If `leading` and `trailing` options are `true` `func` will be called
+     * on the trailing edge of the timeout only if the the throttled function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to throttle.
+     * @param {number} wait The number of milliseconds to throttle executions to.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
+     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+     * @returns {Function} Returns the new throttled function.
+     * @example
+     *
+     * // avoid excessively updating the position while scrolling
+     * var throttled = _.throttle(updatePosition, 100);
+     * jQuery(window).on('scroll', throttled);
+     *
+     * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
+     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+     *   'trailing': false
+     * }));
+     */
+    function throttle(func, wait, options) {
+      var leading = true,
+          trailing = true;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      if (options === false) {
+        leading = false;
+      } else if (isObject(options)) {
+        leading = 'leading' in options ? options.leading : leading;
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+      debounceOptions.leading = leading;
+      debounceOptions.maxWait = wait;
+      debounceOptions.trailing = trailing;
+
+      return debounce(func, wait, debounceOptions);
+    }
+
+    /**
+     * Creates a function that provides `value` to the wrapper function as its
+     * first argument. Additional arguments provided to the function are appended
+     * to those provided to the wrapper function. The wrapper is executed with
+     * the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {*} value The value to wrap.
+     * @param {Function} wrapper The wrapper function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var p = _.wrap(_.escape, function(func, text) {
+     *   return '<p>' + func(text) + '</p>';
+     * });
+     *
+     * p('Fred, Wilma, & Pebbles');
+     * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
+     */
+    function wrap(value, wrapper) {
+      return createWrapper(wrapper, 16, [value]);
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a function that returns `value`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} value The value to return from the new function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * var getter = _.constant(object);
+     * getter() === object;
+     * // => true
+     */
+    function constant(value) {
+      return function() {
+        return value;
+      };
+    }
+
+    /**
+     * Produces a callback bound to an optional `thisArg`. If `func` is a property
+     * name the created callback will return the property value for a given element.
+     * If `func` is an object the created callback will return `true` for elements
+     * that contain the equivalent object properties, otherwise it will return `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} [func=identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of the created callback.
+     * @param {number} [argCount] The number of arguments the callback accepts.
+     * @returns {Function} Returns a callback function.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // wrap to create custom callback shorthands
+     * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
+     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
+     *   return !match ? func(callback, thisArg) : function(object) {
+     *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
+     *   };
+     * });
+     *
+     * _.filter(characters, 'age__gt38');
+     * // => [{ 'name': 'fred', 'age': 40 }]
+     */
+    function createCallback(func, thisArg, argCount) {
+      var type = typeof func;
+      if (func == null || type == 'function') {
+        return baseCreateCallback(func, thisArg, argCount);
+      }
+      // handle "_.pluck" style callback shorthands
+      if (type != 'object') {
+        return property(func);
+      }
+      var props = keys(func),
+          key = props[0],
+          a = func[key];
+
+      // handle "_.where" style callback shorthands
+      if (props.length == 1 && a === a && !isObject(a)) {
+        // fast path the common case of providing an object with a single
+        // property containing a primitive value
+        return function(object) {
+          var b = object[key];
+          return a === b && (a !== 0 || (1 / a == 1 / b));
+        };
+      }
+      return function(object) {
+        var length = props.length,
+            result = false;
+
+        while (length--) {
+          if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+     * corresponding HTML entities.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} string The string to escape.
+     * @returns {string} Returns the escaped string.
+     * @example
+     *
+     * _.escape('Fred, Wilma, & Pebbles');
+     * // => 'Fred, Wilma, &amp; Pebbles'
+     */
+    function escape(string) {
+      return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
+    }
+
+    /**
+     * This method returns the first argument provided to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} value Any value.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * _.identity(object) === object;
+     * // => true
+     */
+    function identity(value) {
+      return value;
+    }
+
+    /**
+     * Adds function properties of a source object to the destination object.
+     * If `object` is a function methods will be added to its prototype as well.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {Function|Object} [object=lodash] object The destination object.
+     * @param {Object} source The object of functions to add.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
+     * @example
+     *
+     * function capitalize(string) {
+     *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+     * }
+     *
+     * _.mixin({ 'capitalize': capitalize });
+     * _.capitalize('fred');
+     * // => 'Fred'
+     *
+     * _('fred').capitalize().value();
+     * // => 'Fred'
+     *
+     * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
+     * _('fred').capitalize();
+     * // => 'Fred'
+     */
+    function mixin(object, source, options) {
+      var chain = true,
+          methodNames = source && functions(source);
+
+      if (!source || (!options && !methodNames.length)) {
+        if (options == null) {
+          options = source;
+        }
+        ctor = lodashWrapper;
+        source = object;
+        object = lodash;
+        methodNames = functions(source);
+      }
+      if (options === false) {
+        chain = false;
+      } else if (isObject(options) && 'chain' in options) {
+        chain = options.chain;
+      }
+      var ctor = object,
+          isFunc = isFunction(ctor);
+
+      forEach(methodNames, function(methodName) {
+        var func = object[methodName] = source[methodName];
+        if (isFunc) {
+          ctor.prototype[methodName] = function() {
+            var chainAll = this.__chain__,
+                value = this.__wrapped__,
+                args = [value];
+
+            push.apply(args, arguments);
+            var result = func.apply(object, args);
+            if (chain || chainAll) {
+              if (value === result && isObject(result)) {
+                return this;
+              }
+              result = new ctor(result);
+              result.__chain__ = chainAll;
+            }
+            return result;
+          };
+        }
+      });
+    }
+
+    /**
+     * Reverts the '_' variable to its previous value and returns a reference to
+     * the `lodash` function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @returns {Function} Returns the `lodash` function.
+     * @example
+     *
+     * var lodash = _.noConflict();
+     */
+    function noConflict() {
+      context._ = oldDash;
+      return this;
+    }
+
+    /**
+     * A no-operation function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * _.noop(object) === undefined;
+     * // => true
+     */
+    function noop() {
+      // no operation performed
+    }
+
+    /**
+     * Gets the number of milliseconds that have elapsed since the Unix epoch
+     * (1 January 1970 00:00:00 UTC).
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @example
+     *
+     * var stamp = _.now();
+     * _.defer(function() { console.log(_.now() - stamp); });
+     * // => logs the number of milliseconds it took for the deferred function to be called
+     */
+    var now = isNative(now = Date.now) && now || function() {
+      return new Date().getTime();
+    };
+
+    /**
+     * Converts the given value into an integer of the specified radix.
+     * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
+     * `value` is a hexadecimal, in which case a `radix` of `16` is used.
+     *
+     * Note: This method avoids differences in native ES3 and ES5 `parseInt`
+     * implementations. See http://es5.github.io/#E.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} value The value to parse.
+     * @param {number} [radix] The radix used to interpret the value to parse.
+     * @returns {number} Returns the new integer value.
+     * @example
+     *
+     * _.parseInt('08');
+     * // => 8
+     */
+    var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
+      // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
+      return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
+    };
+
+    /**
+     * Creates a "_.pluck" style function, which returns the `key` value of a
+     * given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} key The name of the property to retrieve.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'fred',   'age': 40 },
+     *   { 'name': 'barney', 'age': 36 }
+     * ];
+     *
+     * var getName = _.property('name');
+     *
+     * _.map(characters, getName);
+     * // => ['barney', 'fred']
+     *
+     * _.sortBy(characters, getName);
+     * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
+     */
+    function property(key) {
+      return function(object) {
+        return object[key];
+      };
+    }
+
+    /**
+     * Produces a random number between `min` and `max` (inclusive). If only one
+     * argument is provided a number between `0` and the given number will be
+     * returned. If `floating` is truey or either `min` or `max` are floats a
+     * floating-point number will be returned instead of an integer.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {number} [min=0] The minimum possible value.
+     * @param {number} [max=1] The maximum possible value.
+     * @param {boolean} [floating=false] Specify returning a floating-point number.
+     * @returns {number} Returns a random number.
+     * @example
+     *
+     * _.random(0, 5);
+     * // => an integer between 0 and 5
+     *
+     * _.random(5);
+     * // => also an integer between 0 and 5
+     *
+     * _.random(5, true);
+     * // => a floating-point number between 0 and 5
+     *
+     * _.random(1.2, 5.2);
+     * // => a floating-point number between 1.2 and 5.2
+     */
+    function random(min, max, floating) {
+      var noMin = min == null,
+          noMax = max == null;
+
+      if (floating == null) {
+        if (typeof min == 'boolean' && noMax) {
+          floating = min;
+          min = 1;
+        }
+        else if (!noMax && typeof max == 'boolean') {
+          floating = max;
+          noMax = true;
+        }
+      }
+      if (noMin && noMax) {
+        max = 1;
+      }
+      min = +min || 0;
+      if (noMax) {
+        max = min;
+        min = 0;
+      } else {
+        max = +max || 0;
+      }
+      if (floating || min % 1 || max % 1) {
+        var rand = nativeRandom();
+        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
+      }
+      return baseRandom(min, max);
+    }
+
+    /**
+     * Resolves the value of property `key` on `object`. If `key` is a function
+     * it will be invoked with the `this` binding of `object` and its result returned,
+     * else the property value is returned. If `object` is falsey then `undefined`
+     * is returned.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {Object} object The object to inspect.
+     * @param {string} key The name of the property to resolve.
+     * @returns {*} Returns the resolved value.
+     * @example
+     *
+     * var object = {
+     *   'cheese': 'crumpets',
+     *   'stuff': function() {
+     *     return 'nonsense';
+     *   }
+     * };
+     *
+     * _.result(object, 'cheese');
+     * // => 'crumpets'
+     *
+     * _.result(object, 'stuff');
+     * // => 'nonsense'
+     */
+    function result(object, key) {
+      if (object) {
+        var value = object[key];
+        return isFunction(value) ? object[key]() : value;
+      }
+    }
+
+    /**
+     * A micro-templating method that handles arbitrary delimiters, preserves
+     * whitespace, and correctly escapes quotes within interpolated code.
+     *
+     * Note: In the development build, `_.template` utilizes sourceURLs for easier
+     * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+     *
+     * For more information on precompiling templates see:
+     * http://lodash.com/custom-builds
+     *
+     * For more information on Chrome extension sandboxes see:
+     * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} text The template text.
+     * @param {Object} data The data object used to populate the text.
+     * @param {Object} [options] The options object.
+     * @param {RegExp} [options.escape] The "escape" delimiter.
+     * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+     * @param {Object} [options.imports] An object to import into the template as local variables.
+     * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+     * @param {string} [sourceURL] The sourceURL of the template's compiled source.
+     * @param {string} [variable] The data object variable name.
+     * @returns {Function|string} Returns a compiled function when no `data` object
+     *  is given, else it returns the interpolated text.
+     * @example
+     *
+     * // using the "interpolate" delimiter to create a compiled template
+     * var compiled = _.template('hello <%= name %>');
+     * compiled({ 'name': 'fred' });
+     * // => 'hello fred'
+     *
+     * // using the "escape" delimiter to escape HTML in data property values
+     * _.template('<b><%- value %></b>', { 'value': '<script>' });
+     * // => '<b>&lt;script&gt;</b>'
+     *
+     * // using the "evaluate" delimiter to generate HTML
+     * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
+     * _.template(list, { 'people': ['fred', 'barney'] });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+     * _.template('hello ${ name }', { 'name': 'pebbles' });
+     * // => 'hello pebbles'
+     *
+     * // using the internal `print` function in "evaluate" delimiters
+     * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
+     * // => 'hello barney!'
+     *
+     * // using a custom template delimiters
+     * _.templateSettings = {
+     *   'interpolate': /{{([\s\S]+?)}}/g
+     * };
+     *
+     * _.template('hello {{ name }}!', { 'name': 'mustache' });
+     * // => 'hello mustache!'
+     *
+     * // using the `imports` option to import jQuery
+     * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
+     * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the `sourceURL` option to specify a custom sourceURL for the template
+     * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+     * compiled(data);
+     * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+     *
+     * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+     * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+     * compiled.source;
+     * // => function(data) {
+     *   var __t, __p = '', __e = _.escape;
+     *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+     *   return __p;
+     * }
+     *
+     * // using the `source` property to inline compiled templates for meaningful
+     * // line numbers in error messages and a stack trace
+     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+     *   var JST = {\
+     *     "main": ' + _.template(mainText).source + '\
+     *   };\
+     * ');
+     */
+    function template(text, data, options) {
+      // based on John Resig's `tmpl` implementation
+      // http://ejohn.org/blog/javascript-micro-templating/
+      // and Laura Doktorova's doT.js
+      // https://github.com/olado/doT
+      var settings = lodash.templateSettings;
+      text = String(text || '');
+
+      // avoid missing dependencies when `iteratorTemplate` is not defined
+      options = defaults({}, options, settings);
+
+      var imports = defaults({}, options.imports, settings.imports),
+          importsKeys = keys(imports),
+          importsValues = values(imports);
+
+      var isEvaluating,
+          index = 0,
+          interpolate = options.interpolate || reNoMatch,
+          source = "__p += '";
+
+      // compile the regexp to match each delimiter
+      var reDelimiters = RegExp(
+        (options.escape || reNoMatch).source + '|' +
+        interpolate.source + '|' +
+        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+        (options.evaluate || reNoMatch).source + '|$'
+      , 'g');
+
+      text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+        interpolateValue || (interpolateValue = esTemplateValue);
+
+        // escape characters that cannot be included in string literals
+        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+        // replace delimiters with snippets
+        if (escapeValue) {
+          source += "' +\n__e(" + escapeValue + ") +\n'";
+        }
+        if (evaluateValue) {
+          isEvaluating = true;
+          source += "';\n" + evaluateValue + ";\n__p += '";
+        }
+        if (interpolateValue) {
+          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+        }
+        index = offset + match.length;
+
+        // the JS engine embedded in Adobe products requires returning the `match`
+        // string in order to produce the correct `offset` value
+        return match;
+      });
+
+      source += "';\n";
+
+      // if `variable` is not specified, wrap a with-statement around the generated
+      // code to add the data object to the top of the scope chain
+      var variable = options.variable,
+          hasVariable = variable;
+
+      if (!hasVariable) {
+        variable = 'obj';
+        source = 'with (' + variable + ') {\n' + source + '\n}\n';
+      }
+      // cleanup code by stripping empty strings
+      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+        .replace(reEmptyStringMiddle, '$1')
+        .replace(reEmptyStringTrailing, '$1;');
+
+      // frame code as the function body
+      source = 'function(' + variable + ') {\n' +
+        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+        "var __t, __p = '', __e = _.escape" +
+        (isEvaluating
+          ? ', __j = Array.prototype.join;\n' +
+            "function print() { __p += __j.call(arguments, '') }\n"
+          : ';\n'
+        ) +
+        source +
+        'return __p\n}';
+
+      // Use a sourceURL for easier debugging.
+      // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+      var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
+
+      try {
+        var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
+      } catch(e) {
+        e.source = source;
+        throw e;
+      }
+      if (data) {
+        return result(data);
+      }
+      // provide the compiled function's source by its `toString` method, in
+      // supported environments, or the `source` property as a convenience for
+      // inlining compiled templates during the build process
+      result.source = source;
+      return result;
+    }
+
+    /**
+     * Executes the callback `n` times, returning an array of the results
+     * of each callback execution. The callback is bound to `thisArg` and invoked
+     * with one argument; (index).
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {number} n The number of times to execute the callback.
+     * @param {Function} callback The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns an array of the results of each `callback` execution.
+     * @example
+     *
+     * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+     * // => [3, 6, 4]
+     *
+     * _.times(3, function(n) { mage.castSpell(n); });
+     * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+     *
+     * _.times(3, function(n) { this.cast(n); }, mage);
+     * // => also calls `mage.castSpell(n)` three times
+     */
+    function times(n, callback, thisArg) {
+      n = (n = +n) > -1 ? n : 0;
+      var index = -1,
+          result = Array(n);
+
+      callback = baseCreateCallback(callback, thisArg, 1);
+      while (++index < n) {
+        result[index] = callback(index);
+      }
+      return result;
+    }
+
+    /**
+     * The inverse of `_.escape` this method converts the HTML entities
+     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+     * corresponding characters.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} string The string to unescape.
+     * @returns {string} Returns the unescaped string.
+     * @example
+     *
+     * _.unescape('Fred, Barney &amp; Pebbles');
+     * // => 'Fred, Barney & Pebbles'
+     */
+    function unescape(string) {
+      return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
+    }
+
+    /**
+     * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} [prefix] The value to prefix the ID with.
+     * @returns {string} Returns the unique ID.
+     * @example
+     *
+     * _.uniqueId('contact_');
+     * // => 'contact_104'
+     *
+     * _.uniqueId();
+     * // => '105'
+     */
+    function uniqueId(prefix) {
+      var id = ++idCounter;
+      return String(prefix == null ? '' : prefix) + id;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object that wraps the given value with explicit
+     * method chaining enabled.
+     *
+     * @static
+     * @memberOf _
+     * @category Chaining
+     * @param {*} value The value to wrap.
+     * @returns {Object} Returns the wrapper object.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36 },
+     *   { 'name': 'fred',    'age': 40 },
+     *   { 'name': 'pebbles', 'age': 1 }
+     * ];
+     *
+     * var youngest = _.chain(characters)
+     *     .sortBy('age')
+     *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
+     *     .first()
+     *     .value();
+     * // => 'pebbles is 1'
+     */
+    function chain(value) {
+      value = new lodashWrapper(value);
+      value.__chain__ = true;
+      return value;
+    }
+
+    /**
+     * Invokes `interceptor` with the `value` as the first argument and then
+     * returns `value`. The purpose of this method is to "tap into" a method
+     * chain in order to perform operations on intermediate results within
+     * the chain.
+     *
+     * @static
+     * @memberOf _
+     * @category Chaining
+     * @param {*} value The value to provide to `interceptor`.
+     * @param {Function} interceptor The function to invoke.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * _([1, 2, 3, 4])
+     *  .tap(function(array) { array.pop(); })
+     *  .reverse()
+     *  .value();
+     * // => [3, 2, 1]
+     */
+    function tap(value, interceptor) {
+      interceptor(value);
+      return value;
+    }
+
+    /**
+     * Enables explicit method chaining on the wrapper object.
+     *
+     * @name chain
+     * @memberOf _
+     * @category Chaining
+     * @returns {*} Returns the wrapper object.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // without explicit chaining
+     * _(characters).first();
+     * // => { 'name': 'barney', 'age': 36 }
+     *
+     * // with explicit chaining
+     * _(characters).chain()
+     *   .first()
+     *   .pick('age')
+     *   .value();
+     * // => { 'age': 36 }
+     */
+    function wrapperChain() {
+      this.__chain__ = true;
+      return this;
+    }
+
+    /**
+     * Produces the `toString` result of the wrapped value.
+     *
+     * @name toString
+     * @memberOf _
+     * @category Chaining
+     * @returns {string} Returns the string result.
+     * @example
+     *
+     * _([1, 2, 3]).toString();
+     * // => '1,2,3'
+     */
+    function wrapperToString() {
+      return String(this.__wrapped__);
+    }
+
+    /**
+     * Extracts the wrapped value.
+     *
+     * @name valueOf
+     * @memberOf _
+     * @alias value
+     * @category Chaining
+     * @returns {*} Returns the wrapped value.
+     * @example
+     *
+     * _([1, 2, 3]).valueOf();
+     * // => [1, 2, 3]
+     */
+    function wrapperValueOf() {
+      return this.__wrapped__;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions that return wrapped values when chaining
+    lodash.after = after;
+    lodash.assign = assign;
+    lodash.at = at;
+    lodash.bind = bind;
+    lodash.bindAll = bindAll;
+    lodash.bindKey = bindKey;
+    lodash.chain = chain;
+    lodash.compact = compact;
+    lodash.compose = compose;
+    lodash.constant = constant;
+    lodash.countBy = countBy;
+    lodash.create = create;
+    lodash.createCallback = createCallback;
+    lodash.curry = curry;
+    lodash.debounce = debounce;
+    lodash.defaults = defaults;
+    lodash.defer = defer;
+    lodash.delay = delay;
+    lodash.difference = difference;
+    lodash.filter = filter;
+    lodash.flatten = flatten;
+    lodash.forEach = forEach;
+    lodash.forEachRight = forEachRight;
+    lodash.forIn = forIn;
+    lodash.forInRight = forInRight;
+    lodash.forOwn = forOwn;
+    lodash.forOwnRight = forOwnRight;
+    lodash.functions = functions;
+    lodash.groupBy = groupBy;
+    lodash.indexBy = indexBy;
+    lodash.initial = initial;
+    lodash.intersection = intersection;
+    lodash.invert = invert;
+    lodash.invoke = invoke;
+    lodash.keys = keys;
+    lodash.map = map;
+    lodash.mapValues = mapValues;
+    lodash.max = max;
+    lodash.memoize = memoize;
+    lodash.merge = merge;
+    lodash.min = min;
+    lodash.omit = omit;
+    lodash.once = once;
+    lodash.pairs = pairs;
+    lodash.partial = partial;
+    lodash.partialRight = partialRight;
+    lodash.pick = pick;
+    lodash.pluck = pluck;
+    lodash.property = property;
+    lodash.pull = pull;
+    lodash.range = range;
+    lodash.reject = reject;
+    lodash.remove = remove;
+    lodash.rest = rest;
+    lodash.shuffle = shuffle;
+    lodash.sortBy = sortBy;
+    lodash.tap = tap;
+    lodash.throttle = throttle;
+    lodash.times = times;
+    lodash.toArray = toArray;
+    lodash.transform = transform;
+    lodash.union = union;
+    lodash.uniq = uniq;
+    lodash.values = values;
+    lodash.where = where;
+    lodash.without = without;
+    lodash.wrap = wrap;
+    lodash.xor = xor;
+    lodash.zip = zip;
+    lodash.zipObject = zipObject;
+
+    // add aliases
+    lodash.collect = map;
+    lodash.drop = rest;
+    lodash.each = forEach;
+    lodash.eachRight = forEachRight;
+    lodash.extend = assign;
+    lodash.methods = functions;
+    lodash.object = zipObject;
+    lodash.select = filter;
+    lodash.tail = rest;
+    lodash.unique = uniq;
+    lodash.unzip = zip;
+
+    // add functions to `lodash.prototype`
+    mixin(lodash);
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions that return unwrapped values when chaining
+    lodash.clone = clone;
+    lodash.cloneDeep = cloneDeep;
+    lodash.contains = contains;
+    lodash.escape = escape;
+    lodash.every = every;
+    lodash.find = find;
+    lodash.findIndex = findIndex;
+    lodash.findKey = findKey;
+    lodash.findLast = findLast;
+    lodash.findLastIndex = findLastIndex;
+    lodash.findLastKey = findLastKey;
+    lodash.has = has;
+    lodash.identity = identity;
+    lodash.indexOf = indexOf;
+    lodash.isArguments = isArguments;
+    lodash.isArray = isArray;
+    lodash.isBoolean = isBoolean;
+    lodash.isDate = isDate;
+    lodash.isElement = isElement;
+    lodash.isEmpty = isEmpty;
+    lodash.isEqual = isEqual;
+    lodash.isFinite = isFinite;
+    lodash.isFunction = isFunction;
+    lodash.isNaN = isNaN;
+    lodash.isNull = isNull;
+    lodash.isNumber = isNumber;
+    lodash.isObject = isObject;
+    lodash.isPlainObject = isPlainObject;
+    lodash.isRegExp = isRegExp;
+    lodash.isString = isString;
+    lodash.isUndefined = isUndefined;
+    lodash.lastIndexOf = lastIndexOf;
+    lodash.mixin = mixin;
+    lodash.noConflict = noConflict;
+    lodash.noop = noop;
+    lodash.now = now;
+    lodash.parseInt = parseInt;
+    lodash.random = random;
+    lodash.reduce = reduce;
+    lodash.reduceRight = reduceRight;
+    lodash.result = result;
+    lodash.runInContext = runInContext;
+    lodash.size = size;
+    lodash.some = some;
+    lodash.sortedIndex = sortedIndex;
+    lodash.template = template;
+    lodash.unescape = unescape;
+    lodash.uniqueId = uniqueId;
+
+    // add aliases
+    lodash.all = every;
+    lodash.any = some;
+    lodash.detect = find;
+    lodash.findWhere = find;
+    lodash.foldl = reduce;
+    lodash.foldr = reduceRight;
+    lodash.include = contains;
+    lodash.inject = reduce;
+
+    mixin(function() {
+      var source = {}
+      forOwn(lodash, function(func, methodName) {
+        if (!lodash.prototype[methodName]) {
+          source[methodName] = func;
+        }
+      });
+      return source;
+    }(), false);
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions capable of returning wrapped and unwrapped values when chaining
+    lodash.first = first;
+    lodash.last = last;
+    lodash.sample = sample;
+
+    // add aliases
+    lodash.take = first;
+    lodash.head = first;
+
+    forOwn(lodash, function(func, methodName) {
+      var callbackable = methodName !== 'sample';
+      if (!lodash.prototype[methodName]) {
+        lodash.prototype[methodName]= function(n, guard) {
+          var chainAll = this.__chain__,
+              result = func(this.__wrapped__, n, guard);
+
+          return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
+            ? result
+            : new lodashWrapper(result, chainAll);
+        };
+      }
+    });
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The semantic version number.
+     *
+     * @static
+     * @memberOf _
+     * @type string
+     */
+    lodash.VERSION = '2.4.1';
+
+    // add "Chaining" functions to the wrapper
+    lodash.prototype.chain = wrapperChain;
+    lodash.prototype.toString = wrapperToString;
+    lodash.prototype.value = wrapperValueOf;
+    lodash.prototype.valueOf = wrapperValueOf;
+
+    // add `Array` functions that return unwrapped values
+    forEach(['join', 'pop', 'shift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        var chainAll = this.__chain__,
+            result = func.apply(this.__wrapped__, arguments);
+
+        return chainAll
+          ? new lodashWrapper(result, chainAll)
+          : result;
+      };
+    });
+
+    // add `Array` functions that return the existing wrapped value
+    forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        func.apply(this.__wrapped__, arguments);
+        return this;
+      };
+    });
+
+    // add `Array` functions that return new wrapped values
+    forEach(['concat', 'slice', 'splice'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
+      };
+    });
+
+    return lodash;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Lo-Dash
+  var _ = runInContext();
+
+  // some AMD build optimizers like r.js check for condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash is loaded with a RequireJS shim config.
+    // See http://requirejs.org/docs/api.html#config-shim
+    root._ = _;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return _;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports && freeModule) {
+    // in Node.js or RingoJS
+    if (moduleExports) {
+      (freeModule.exports = _)._ = _;
+    }
+    // in Narwhal or Rhino -require
+    else {
+      freeExports._ = _;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    root._ = _;
+  }
+}.call(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.min.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.min.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.min.js	(revision 533)
@@ -0,0 +1,56 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
+ * Build: `lodash modern -o ./dist/lodash.js`
+ */
+;(function(){function n(n,t,e){e=(e||0)-1;for(var r=n?n.length:0;++e<r;)if(n[e]===t)return e;return-1}function t(t,e){var r=typeof e;if(t=t.l,"boolean"==r||null==e)return t[e]?0:-1;"number"!=r&&"string"!=r&&(r="object");var u="number"==r?e:m+e;return t=(t=t[r])&&t[u],"object"==r?t&&-1<n(t,e)?0:-1:t?0:-1}function e(n){var t=this.l,e=typeof n;if("boolean"==e||null==n)t[n]=true;else{"number"!=e&&"string"!=e&&(e="object");var r="number"==e?n:m+n,t=t[e]||(t[e]={});"object"==e?(t[r]||(t[r]=[])).push(n):t[r]=true
+}}function r(n){return n.charCodeAt(0)}function u(n,t){for(var e=n.m,r=t.m,u=-1,o=e.length;++u<o;){var i=e[u],a=r[u];if(i!==a){if(i>a||typeof i=="undefined")return 1;if(i<a||typeof a=="undefined")return-1}}return n.n-t.n}function o(n){var t=-1,r=n.length,u=n[0],o=n[r/2|0],i=n[r-1];if(u&&typeof u=="object"&&o&&typeof o=="object"&&i&&typeof i=="object")return false;for(u=f(),u["false"]=u["null"]=u["true"]=u.undefined=false,o=f(),o.k=n,o.l=u,o.push=e;++t<r;)o.push(n[t]);return o}function i(n){return"\\"+U[n]
+}function a(){return h.pop()||[]}function f(){return g.pop()||{k:null,l:null,m:null,"false":false,n:0,"null":false,number:null,object:null,push:null,string:null,"true":false,undefined:false,o:null}}function l(n){n.length=0,h.length<_&&h.push(n)}function c(n){var t=n.l;t&&c(t),n.k=n.l=n.m=n.object=n.number=n.string=n.o=null,g.length<_&&g.push(n)}function p(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);var r=-1;e=e-t||0;for(var u=Array(0>e?0:e);++r<e;)u[r]=n[t+r];return u}function s(e){function h(n,t,e){if(!n||!V[typeof n])return n;
+t=t&&typeof e=="undefined"?t:tt(t,e,3);for(var r=-1,u=V[typeof n]&&Fe(n),o=u?u.length:0;++r<o&&(e=u[r],false!==t(n[e],e,n)););return n}function g(n,t,e){var r;if(!n||!V[typeof n])return n;t=t&&typeof e=="undefined"?t:tt(t,e,3);for(r in n)if(false===t(n[r],r,n))break;return n}function _(n,t,e){var r,u=n,o=u;if(!u)return o;for(var i=arguments,a=0,f=typeof e=="number"?2:i.length;++a<f;)if((u=i[a])&&V[typeof u])for(var l=-1,c=V[typeof u]&&Fe(u),p=c?c.length:0;++l<p;)r=c[l],"undefined"==typeof o[r]&&(o[r]=u[r]);
+return o}function U(n,t,e){var r,u=n,o=u;if(!u)return o;var i=arguments,a=0,f=typeof e=="number"?2:i.length;if(3<f&&"function"==typeof i[f-2])var l=tt(i[--f-1],i[f--],2);else 2<f&&"function"==typeof i[f-1]&&(l=i[--f]);for(;++a<f;)if((u=i[a])&&V[typeof u])for(var c=-1,p=V[typeof u]&&Fe(u),s=p?p.length:0;++c<s;)r=p[c],o[r]=l?l(o[r],u[r]):u[r];return o}function H(n){var t,e=[];if(!n||!V[typeof n])return e;for(t in n)me.call(n,t)&&e.push(t);return e}function J(n){return n&&typeof n=="object"&&!Te(n)&&me.call(n,"__wrapped__")?n:new Q(n)
+}function Q(n,t){this.__chain__=!!t,this.__wrapped__=n}function X(n){function t(){if(r){var n=p(r);be.apply(n,arguments)}if(this instanceof t){var o=nt(e.prototype),n=e.apply(o,n||arguments);return wt(n)?n:o}return e.apply(u,n||arguments)}var e=n[0],r=n[2],u=n[4];return $e(t,n),t}function Z(n,t,e,r,u){if(e){var o=e(n);if(typeof o!="undefined")return o}if(!wt(n))return n;var i=ce.call(n);if(!K[i])return n;var f=Ae[i];switch(i){case T:case F:return new f(+n);case W:case P:return new f(n);case z:return o=f(n.source,C.exec(n)),o.lastIndex=n.lastIndex,o
+}if(i=Te(n),t){var c=!r;r||(r=a()),u||(u=a());for(var s=r.length;s--;)if(r[s]==n)return u[s];o=i?f(n.length):{}}else o=i?p(n):U({},n);return i&&(me.call(n,"index")&&(o.index=n.index),me.call(n,"input")&&(o.input=n.input)),t?(r.push(n),u.push(o),(i?St:h)(n,function(n,i){o[i]=Z(n,t,e,r,u)}),c&&(l(r),l(u)),o):o}function nt(n){return wt(n)?ke(n):{}}function tt(n,t,e){if(typeof n!="function")return Ut;if(typeof t=="undefined"||!("prototype"in n))return n;var r=n.__bindData__;if(typeof r=="undefined"&&(De.funcNames&&(r=!n.name),r=r||!De.funcDecomp,!r)){var u=ge.call(n);
+De.funcNames||(r=!O.test(u)),r||(r=E.test(u),$e(n,r))}if(false===r||true!==r&&1&r[1])return n;switch(e){case 1:return function(e){return n.call(t,e)};case 2:return function(e,r){return n.call(t,e,r)};case 3:return function(e,r,u){return n.call(t,e,r,u)};case 4:return function(e,r,u,o){return n.call(t,e,r,u,o)}}return Mt(n,t)}function et(n){function t(){var n=f?i:this;if(u){var h=p(u);be.apply(h,arguments)}return(o||c)&&(h||(h=p(arguments)),o&&be.apply(h,o),c&&h.length<a)?(r|=16,et([e,s?r:-4&r,h,null,i,a])):(h||(h=arguments),l&&(e=n[v]),this instanceof t?(n=nt(e.prototype),h=e.apply(n,h),wt(h)?h:n):e.apply(n,h))
+}var e=n[0],r=n[1],u=n[2],o=n[3],i=n[4],a=n[5],f=1&r,l=2&r,c=4&r,s=8&r,v=e;return $e(t,n),t}function rt(e,r){var u=-1,i=st(),a=e?e.length:0,f=a>=b&&i===n,l=[];if(f){var p=o(r);p?(i=t,r=p):f=false}for(;++u<a;)p=e[u],0>i(r,p)&&l.push(p);return f&&c(r),l}function ut(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r<u;){var i=n[r];if(i&&typeof i=="object"&&typeof i.length=="number"&&(Te(i)||yt(i))){t||(i=ut(i,t,e));var a=-1,f=i.length,l=o.length;for(o.length+=f;++a<f;)o[l++]=i[a]}else e||o.push(i)}return o
+}function ot(n,t,e,r,u,o){if(e){var i=e(n,t);if(typeof i!="undefined")return!!i}if(n===t)return 0!==n||1/n==1/t;if(n===n&&!(n&&V[typeof n]||t&&V[typeof t]))return false;if(null==n||null==t)return n===t;var f=ce.call(n),c=ce.call(t);if(f==D&&(f=q),c==D&&(c=q),f!=c)return false;switch(f){case T:case F:return+n==+t;case W:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case z:case P:return n==oe(t)}if(c=f==$,!c){var p=me.call(n,"__wrapped__"),s=me.call(t,"__wrapped__");if(p||s)return ot(p?n.__wrapped__:n,s?t.__wrapped__:t,e,r,u,o);
+if(f!=q)return false;if(f=n.constructor,p=t.constructor,f!=p&&!(dt(f)&&f instanceof f&&dt(p)&&p instanceof p)&&"constructor"in n&&"constructor"in t)return false}for(f=!u,u||(u=a()),o||(o=a()),p=u.length;p--;)if(u[p]==n)return o[p]==t;var v=0,i=true;if(u.push(n),o.push(t),c){if(p=n.length,v=t.length,(i=v==p)||r)for(;v--;)if(c=p,s=t[v],r)for(;c--&&!(i=ot(n[c],s,e,r,u,o)););else if(!(i=ot(n[v],s,e,r,u,o)))break}else g(t,function(t,a,f){return me.call(f,a)?(v++,i=me.call(n,a)&&ot(n[a],t,e,r,u,o)):void 0}),i&&!r&&g(n,function(n,t,e){return me.call(e,t)?i=-1<--v:void 0
+});return u.pop(),o.pop(),f&&(l(u),l(o)),i}function it(n,t,e,r,u){(Te(t)?St:h)(t,function(t,o){var i,a,f=t,l=n[o];if(t&&((a=Te(t))||Pe(t))){for(f=r.length;f--;)if(i=r[f]==t){l=u[f];break}if(!i){var c;e&&(f=e(l,t),c=typeof f!="undefined")&&(l=f),c||(l=a?Te(l)?l:[]:Pe(l)?l:{}),r.push(t),u.push(l),c||it(l,t,e,r,u)}}else e&&(f=e(l,t),typeof f=="undefined"&&(f=t)),typeof f!="undefined"&&(l=f);n[o]=l})}function at(n,t){return n+he(Re()*(t-n+1))}function ft(e,r,u){var i=-1,f=st(),p=e?e.length:0,s=[],v=!r&&p>=b&&f===n,h=u||v?a():s;
+for(v&&(h=o(h),f=t);++i<p;){var g=e[i],y=u?u(g,i,e):g;(r?!i||h[h.length-1]!==y:0>f(h,y))&&((u||v)&&h.push(y),s.push(g))}return v?(l(h.k),c(h)):u&&l(h),s}function lt(n){return function(t,e,r){var u={};e=J.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r<o;){var i=t[r];n(u,i,e(i,r,t),t)}else h(t,function(t,r,o){n(u,t,e(t,r,o),o)});return u}}function ct(n,t,e,r,u,o){var i=1&t,a=4&t,f=16&t,l=32&t;if(!(2&t||dt(n)))throw new ie;f&&!e.length&&(t&=-17,f=e=false),l&&!r.length&&(t&=-33,l=r=false);
+var c=n&&n.__bindData__;return c&&true!==c?(c=p(c),c[2]&&(c[2]=p(c[2])),c[3]&&(c[3]=p(c[3])),!i||1&c[1]||(c[4]=u),!i&&1&c[1]&&(t|=8),!a||4&c[1]||(c[5]=o),f&&be.apply(c[2]||(c[2]=[]),e),l&&we.apply(c[3]||(c[3]=[]),r),c[1]|=t,ct.apply(null,c)):(1==t||17===t?X:et)([n,t,e,r,u,o])}function pt(n){return Be[n]}function st(){var t=(t=J.indexOf)===Wt?n:t;return t}function vt(n){return typeof n=="function"&&pe.test(n)}function ht(n){var t,e;return n&&ce.call(n)==q&&(t=n.constructor,!dt(t)||t instanceof t)?(g(n,function(n,t){e=t
+}),typeof e=="undefined"||me.call(n,e)):false}function gt(n){return We[n]}function yt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ce.call(n)==D||false}function mt(n,t,e){var r=Fe(n),u=r.length;for(t=tt(t,e,3);u--&&(e=r[u],false!==t(n[e],e,n)););return n}function bt(n){var t=[];return g(n,function(n,e){dt(n)&&t.push(e)}),t.sort()}function _t(n){for(var t=-1,e=Fe(n),r=e.length,u={};++t<r;){var o=e[t];u[n[o]]=o}return u}function dt(n){return typeof n=="function"}function wt(n){return!(!n||!V[typeof n])
+}function jt(n){return typeof n=="number"||n&&typeof n=="object"&&ce.call(n)==W||false}function kt(n){return typeof n=="string"||n&&typeof n=="object"&&ce.call(n)==P||false}function xt(n){for(var t=-1,e=Fe(n),r=e.length,u=Xt(r);++t<r;)u[t]=n[e[t]];return u}function Ct(n,t,e){var r=-1,u=st(),o=n?n.length:0,i=false;return e=(0>e?Ie(0,o+e):e)||0,Te(n)?i=-1<u(n,t,e):typeof o=="number"?i=-1<(kt(n)?n.indexOf(t,e):u(n,t,e)):h(n,function(n){return++r<e?void 0:!(i=n===t)}),i}function Ot(n,t,e){var r=true;t=J.createCallback(t,e,3),e=-1;
+var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&(r=!!t(n[e],e,n)););else h(n,function(n,e,u){return r=!!t(n,e,u)});return r}function Nt(n,t,e){var r=[];t=J.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u;){var o=n[e];t(o,e,n)&&r.push(o)}else h(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function It(n,t,e){t=J.createCallback(t,e,3),e=-1;var r=n?n.length:0;if(typeof r!="number"){var u;return h(n,function(n,e,r){return t(n,e,r)?(u=n,false):void 0}),u}for(;++e<r;){var o=n[e];
+if(t(o,e,n))return o}}function St(n,t,e){var r=-1,u=n?n.length:0;if(t=t&&typeof e=="undefined"?t:tt(t,e,3),typeof u=="number")for(;++r<u&&false!==t(n[r],r,n););else h(n,t);return n}function Et(n,t,e){var r=n?n.length:0;if(t=t&&typeof e=="undefined"?t:tt(t,e,3),typeof r=="number")for(;r--&&false!==t(n[r],r,n););else{var u=Fe(n),r=u.length;h(n,function(n,e,o){return e=u?u[--r]:--r,t(o[e],e,o)})}return n}function Rt(n,t,e){var r=-1,u=n?n.length:0;if(t=J.createCallback(t,e,3),typeof u=="number")for(var o=Xt(u);++r<u;)o[r]=t(n[r],r,n);
+else o=[],h(n,function(n,e,u){o[++r]=t(n,e,u)});return o}function At(n,t,e){var u=-1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&Te(n)){e=-1;for(var i=n.length;++e<i;){var a=n[e];a>o&&(o=a)}}else t=null==t&&kt(n)?r:J.createCallback(t,e,3),St(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Dt(n,t,e,r){if(!n)return e;var u=3>arguments.length;t=J.createCallback(t,r,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(e=n[++o]);++o<i;)e=t(e,n[o],o,n);else h(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)
+});return e}function $t(n,t,e,r){var u=3>arguments.length;return t=J.createCallback(t,r,4),Et(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Tt(n){var t=-1,e=n?n.length:0,r=Xt(typeof e=="number"?e:0);return St(n,function(n){var e=at(0,++t);r[t]=r[e],r[e]=n}),r}function Ft(n,t,e){var r;t=J.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&!(r=t(n[e],e,n)););else h(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function Bt(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=-1;
+for(t=J.createCallback(t,e,3);++o<u&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[0]:v;return p(n,0,Se(Ie(0,r),u))}function Wt(t,e,r){if(typeof r=="number"){var u=t?t.length:0;r=0>r?Ie(0,u+r):r||0}else if(r)return r=zt(t,e),t[r]===e?r:-1;return n(t,e,r)}function qt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=J.createCallback(t,e,3);++u<o&&t(n[u],u,n);)r++}else r=null==t||e?1:Ie(0,t);return p(n,r)}function zt(n,t,e,r){var u=0,o=n?n.length:u;for(e=e?J.createCallback(e,r,1):Ut,t=e(t);u<o;)r=u+o>>>1,e(n[r])<t?u=r+1:o=r;
+return u}function Pt(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(e=J.createCallback(e,r,3)),ft(n,t,e)}function Kt(){for(var n=1<arguments.length?arguments:arguments[0],t=-1,e=n?At(Ve(n,"length")):0,r=Xt(0>e?0:e);++t<e;)r[t]=Ve(n,t);return r}function Lt(n,t){var e=-1,r=n?n.length:0,u={};for(t||!r||Te(n[0])||(t=[]);++e<r;){var o=n[e];t?u[o]=t[e]:o&&(u[o[0]]=o[1])}return u}function Mt(n,t){return 2<arguments.length?ct(n,17,p(arguments,2),null,t):ct(n,1,null,null,t)
+}function Vt(n,t,e){function r(){c&&ve(c),i=c=p=v,(g||h!==t)&&(s=Ue(),a=n.apply(l,o),c||i||(o=l=null))}function u(){var e=t-(Ue()-f);0<e?c=_e(u,e):(i&&ve(i),e=p,i=c=p=v,e&&(s=Ue(),a=n.apply(l,o),c||i||(o=l=null)))}var o,i,a,f,l,c,p,s=0,h=false,g=true;if(!dt(n))throw new ie;if(t=Ie(0,t)||0,true===e)var y=true,g=false;else wt(e)&&(y=e.leading,h="maxWait"in e&&(Ie(t,e.maxWait)||0),g="trailing"in e?e.trailing:g);return function(){if(o=arguments,f=Ue(),l=this,p=g&&(c||!y),false===h)var e=y&&!c;else{i||y||(s=f);var v=h-(f-s),m=0>=v;
+m?(i&&(i=ve(i)),s=f,a=n.apply(l,o)):i||(i=_e(r,v))}return m&&c?c=ve(c):c||t===h||(c=_e(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Ut(n){return n}function Gt(n,t,e){var r=true,u=t&&bt(t);t&&(e||u.length)||(null==e&&(e=t),o=Q,t=n,n=J,u=bt(t)),false===e?r=false:wt(e)&&"chain"in e&&(r=e.chain);var o=n,i=dt(o);St(u,function(e){var u=n[e]=t[e];i&&(o.prototype[e]=function(){var t=this.__chain__,e=this.__wrapped__,i=[e];if(be.apply(i,arguments),i=u.apply(n,i),r||t){if(e===i&&wt(i))return this;
+i=new o(i),i.__chain__=t}return i})})}function Ht(){}function Jt(n){return function(t){return t[n]}}function Qt(){return this.__wrapped__}e=e?Y.defaults(G.Object(),e,Y.pick(G,A)):G;var Xt=e.Array,Yt=e.Boolean,Zt=e.Date,ne=e.Function,te=e.Math,ee=e.Number,re=e.Object,ue=e.RegExp,oe=e.String,ie=e.TypeError,ae=[],fe=re.prototype,le=e._,ce=fe.toString,pe=ue("^"+oe(ce).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),se=te.ceil,ve=e.clearTimeout,he=te.floor,ge=ne.prototype.toString,ye=vt(ye=re.getPrototypeOf)&&ye,me=fe.hasOwnProperty,be=ae.push,_e=e.setTimeout,de=ae.splice,we=ae.unshift,je=function(){try{var n={},t=vt(t=re.defineProperty)&&t,e=t(n,n,n)&&t
+}catch(r){}return e}(),ke=vt(ke=re.create)&&ke,xe=vt(xe=Xt.isArray)&&xe,Ce=e.isFinite,Oe=e.isNaN,Ne=vt(Ne=re.keys)&&Ne,Ie=te.max,Se=te.min,Ee=e.parseInt,Re=te.random,Ae={};Ae[$]=Xt,Ae[T]=Yt,Ae[F]=Zt,Ae[B]=ne,Ae[q]=re,Ae[W]=ee,Ae[z]=ue,Ae[P]=oe,Q.prototype=J.prototype;var De=J.support={};De.funcDecomp=!vt(e.a)&&E.test(s),De.funcNames=typeof ne.name=="string",J.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:N,variable:"",imports:{_:J}},ke||(nt=function(){function n(){}return function(t){if(wt(t)){n.prototype=t;
+var r=new n;n.prototype=null}return r||e.Object()}}());var $e=je?function(n,t){M.value=t,je(n,"__bindData__",M)}:Ht,Te=xe||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ce.call(n)==$||false},Fe=Ne?function(n){return wt(n)?Ne(n):[]}:H,Be={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},We=_t(Be),qe=ue("("+Fe(We).join("|")+")","g"),ze=ue("["+Fe(Be).join("")+"]","g"),Pe=ye?function(n){if(!n||ce.call(n)!=q)return false;var t=n.valueOf,e=vt(t)&&(e=ye(t))&&ye(e);return e?n==e||ye(n)==e:ht(n)
+}:ht,Ke=lt(function(n,t,e){me.call(n,e)?n[e]++:n[e]=1}),Le=lt(function(n,t,e){(me.call(n,e)?n[e]:n[e]=[]).push(t)}),Me=lt(function(n,t,e){n[e]=t}),Ve=Rt,Ue=vt(Ue=Zt.now)&&Ue||function(){return(new Zt).getTime()},Ge=8==Ee(d+"08")?Ee:function(n,t){return Ee(kt(n)?n.replace(I,""):n,t||0)};return J.after=function(n,t){if(!dt(t))throw new ie;return function(){return 1>--n?t.apply(this,arguments):void 0}},J.assign=U,J.at=function(n){for(var t=arguments,e=-1,r=ut(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=Xt(t);++e<t;)u[e]=n[r[e]];
+return u},J.bind=Mt,J.bindAll=function(n){for(var t=1<arguments.length?ut(arguments,true,false,1):bt(n),e=-1,r=t.length;++e<r;){var u=t[e];n[u]=ct(n[u],1,null,null,n)}return n},J.bindKey=function(n,t){return 2<arguments.length?ct(t,19,p(arguments,2),null,n):ct(t,3,null,null,n)},J.chain=function(n){return n=new Q(n),n.__chain__=true,n},J.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},J.compose=function(){for(var n=arguments,t=n.length;t--;)if(!dt(n[t]))throw new ie;
+return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];return t[0]}},J.constant=function(n){return function(){return n}},J.countBy=Ke,J.create=function(n,t){var e=nt(n);return t?U(e,t):e},J.createCallback=function(n,t,e){var r=typeof n;if(null==n||"function"==r)return tt(n,t,e);if("object"!=r)return Jt(n);var u=Fe(n),o=u[0],i=n[o];return 1!=u.length||i!==i||wt(i)?function(t){for(var e=u.length,r=false;e--&&(r=ot(t[u[e]],n[u[e]],null,true)););return r}:function(n){return n=n[o],i===n&&(0!==i||1/i==1/n)
+}},J.curry=function(n,t){return t=typeof t=="number"?t:+t||n.length,ct(n,4,null,null,null,t)},J.debounce=Vt,J.defaults=_,J.defer=function(n){if(!dt(n))throw new ie;var t=p(arguments,1);return _e(function(){n.apply(v,t)},1)},J.delay=function(n,t){if(!dt(n))throw new ie;var e=p(arguments,2);return _e(function(){n.apply(v,e)},t)},J.difference=function(n){return rt(n,ut(arguments,true,true,1))},J.filter=Nt,J.flatten=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(n=Rt(n,e,r)),ut(n,t)
+},J.forEach=St,J.forEachRight=Et,J.forIn=g,J.forInRight=function(n,t,e){var r=[];g(n,function(n,t){r.push(t,n)});var u=r.length;for(t=tt(t,e,3);u--&&false!==t(r[u--],r[u],n););return n},J.forOwn=h,J.forOwnRight=mt,J.functions=bt,J.groupBy=Le,J.indexBy=Me,J.initial=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=J.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return p(n,0,Se(Ie(0,u-r),u))},J.intersection=function(){for(var e=[],r=-1,u=arguments.length,i=a(),f=st(),p=f===n,s=a();++r<u;){var v=arguments[r];
+(Te(v)||yt(v))&&(e.push(v),i.push(p&&v.length>=b&&o(r?e[r]:s)))}var p=e[0],h=-1,g=p?p.length:0,y=[];n:for(;++h<g;){var m=i[0],v=p[h];if(0>(m?t(m,v):f(s,v))){for(r=u,(m||s).push(v);--r;)if(m=i[r],0>(m?t(m,v):f(e[r],v)))continue n;y.push(v)}}for(;u--;)(m=i[u])&&c(m);return l(i),l(s),y},J.invert=_t,J.invoke=function(n,t){var e=p(arguments,2),r=-1,u=typeof t=="function",o=n?n.length:0,i=Xt(typeof o=="number"?o:0);return St(n,function(n){i[++r]=(u?t:n[t]).apply(n,e)}),i},J.keys=Fe,J.map=Rt,J.mapValues=function(n,t,e){var r={};
+return t=J.createCallback(t,e,3),h(n,function(n,e,u){r[e]=t(n,e,u)}),r},J.max=At,J.memoize=function(n,t){function e(){var r=e.cache,u=t?t.apply(this,arguments):m+arguments[0];return me.call(r,u)?r[u]:r[u]=n.apply(this,arguments)}if(!dt(n))throw new ie;return e.cache={},e},J.merge=function(n){var t=arguments,e=2;if(!wt(n))return n;if("number"!=typeof t[2]&&(e=t.length),3<e&&"function"==typeof t[e-2])var r=tt(t[--e-1],t[e--],2);else 2<e&&"function"==typeof t[e-1]&&(r=t[--e]);for(var t=p(arguments,1,e),u=-1,o=a(),i=a();++u<e;)it(n,t[u],r,o,i);
+return l(o),l(i),n},J.min=function(n,t,e){var u=1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&Te(n)){e=-1;for(var i=n.length;++e<i;){var a=n[e];a<o&&(o=a)}}else t=null==t&&kt(n)?r:J.createCallback(t,e,3),St(n,function(n,e,r){e=t(n,e,r),e<u&&(u=e,o=n)});return o},J.omit=function(n,t,e){var r={};if(typeof t!="function"){var u=[];g(n,function(n,t){u.push(t)});for(var u=rt(u,ut(arguments,true,false,1)),o=-1,i=u.length;++o<i;){var a=u[o];r[a]=n[a]}}else t=J.createCallback(t,e,3),g(n,function(n,e,u){t(n,e,u)||(r[e]=n)
+});return r},J.once=function(n){var t,e;if(!dt(n))throw new ie;return function(){return t?e:(t=true,e=n.apply(this,arguments),n=null,e)}},J.pairs=function(n){for(var t=-1,e=Fe(n),r=e.length,u=Xt(r);++t<r;){var o=e[t];u[t]=[o,n[o]]}return u},J.partial=function(n){return ct(n,16,p(arguments,1))},J.partialRight=function(n){return ct(n,32,null,p(arguments,1))},J.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=-1,o=ut(arguments,true,false,1),i=wt(n)?o.length:0;++u<i;){var a=o[u];a in n&&(r[a]=n[a])
+}else t=J.createCallback(t,e,3),g(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},J.pluck=Ve,J.property=Jt,J.pull=function(n){for(var t=arguments,e=0,r=t.length,u=n?n.length:0;++e<r;)for(var o=-1,i=t[e];++o<u;)n[o]===i&&(de.call(n,o--,1),u--);return n},J.range=function(n,t,e){n=+n||0,e=typeof e=="number"?e:+e||1,null==t&&(t=n,n=0);var r=-1;t=Ie(0,se((t-n)/(e||1)));for(var u=Xt(t);++r<t;)u[r]=n,n+=e;return u},J.reject=function(n,t,e){return t=J.createCallback(t,e,3),Nt(n,function(n,e,r){return!t(n,e,r)
+})},J.remove=function(n,t,e){var r=-1,u=n?n.length:0,o=[];for(t=J.createCallback(t,e,3);++r<u;)e=n[r],t(e,r,n)&&(o.push(e),de.call(n,r--,1),u--);return o},J.rest=qt,J.shuffle=Tt,J.sortBy=function(n,t,e){var r=-1,o=Te(t),i=n?n.length:0,p=Xt(typeof i=="number"?i:0);for(o||(t=J.createCallback(t,e,3)),St(n,function(n,e,u){var i=p[++r]=f();o?i.m=Rt(t,function(t){return n[t]}):(i.m=a())[0]=t(n,e,u),i.n=r,i.o=n}),i=p.length,p.sort(u);i--;)n=p[i],p[i]=n.o,o||l(n.m),c(n);return p},J.tap=function(n,t){return t(n),n
+},J.throttle=function(n,t,e){var r=true,u=true;if(!dt(n))throw new ie;return false===e?r=false:wt(e)&&(r="leading"in e?e.leading:r,u="trailing"in e?e.trailing:u),L.leading=r,L.maxWait=t,L.trailing=u,Vt(n,t,L)},J.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=Xt(n);for(t=tt(t,e,1);++r<n;)u[r]=t(r);return u},J.toArray=function(n){return n&&typeof n.length=="number"?p(n):xt(n)},J.transform=function(n,t,e,r){var u=Te(n);if(null==e)if(u)e=[];else{var o=n&&n.constructor;e=nt(o&&o.prototype)}return t&&(t=J.createCallback(t,r,4),(u?St:h)(n,function(n,r,u){return t(e,n,r,u)
+})),e},J.union=function(){return ft(ut(arguments,true,true))},J.uniq=Pt,J.values=xt,J.where=Nt,J.without=function(n){return rt(n,p(arguments,1))},J.wrap=function(n,t){return ct(t,16,[n])},J.xor=function(){for(var n=-1,t=arguments.length;++n<t;){var e=arguments[n];if(Te(e)||yt(e))var r=r?ft(rt(r,e).concat(rt(e,r))):e}return r||[]},J.zip=Kt,J.zipObject=Lt,J.collect=Rt,J.drop=qt,J.each=St,J.eachRight=Et,J.extend=U,J.methods=bt,J.object=Lt,J.select=Nt,J.tail=qt,J.unique=Pt,J.unzip=Kt,Gt(J),J.clone=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=t,t=false),Z(n,t,typeof e=="function"&&tt(e,r,1))
+},J.cloneDeep=function(n,t,e){return Z(n,true,typeof t=="function"&&tt(t,e,1))},J.contains=Ct,J.escape=function(n){return null==n?"":oe(n).replace(ze,pt)},J.every=Ot,J.find=It,J.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;for(t=J.createCallback(t,e,3);++r<u;)if(t(n[r],r,n))return r;return-1},J.findKey=function(n,t,e){var r;return t=J.createCallback(t,e,3),h(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},J.findLast=function(n,t,e){var r;return t=J.createCallback(t,e,3),Et(n,function(n,e,u){return t(n,e,u)?(r=n,false):void 0
+}),r},J.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=J.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},J.findLastKey=function(n,t,e){var r;return t=J.createCallback(t,e,3),mt(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},J.has=function(n,t){return n?me.call(n,t):false},J.identity=Ut,J.indexOf=Wt,J.isArguments=yt,J.isArray=Te,J.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ce.call(n)==T||false},J.isDate=function(n){return n&&typeof n=="object"&&ce.call(n)==F||false
+},J.isElement=function(n){return n&&1===n.nodeType||false},J.isEmpty=function(n){var t=true;if(!n)return t;var e=ce.call(n),r=n.length;return e==$||e==P||e==D||e==q&&typeof r=="number"&&dt(n.splice)?!r:(h(n,function(){return t=false}),t)},J.isEqual=function(n,t,e,r){return ot(n,t,typeof e=="function"&&tt(e,r,2))},J.isFinite=function(n){return Ce(n)&&!Oe(parseFloat(n))},J.isFunction=dt,J.isNaN=function(n){return jt(n)&&n!=+n},J.isNull=function(n){return null===n},J.isNumber=jt,J.isObject=wt,J.isPlainObject=Pe,J.isRegExp=function(n){return n&&typeof n=="object"&&ce.call(n)==z||false
+},J.isString=kt,J.isUndefined=function(n){return typeof n=="undefined"},J.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?Ie(0,r+e):Se(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},J.mixin=Gt,J.noConflict=function(){return e._=le,this},J.noop=Ht,J.now=Ue,J.parseInt=Ge,J.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Re(),Se(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):at(n,t)
+},J.reduce=Dt,J.reduceRight=$t,J.result=function(n,t){if(n){var e=n[t];return dt(e)?n[t]():e}},J.runInContext=s,J.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Fe(n).length},J.some=Ft,J.sortedIndex=zt,J.template=function(n,t,e){var r=J.templateSettings;n=oe(n||""),e=_({},e,r);var u,o=_({},e.imports,r.imports),r=Fe(o),o=xt(o),a=0,f=e.interpolate||S,l="__p+='",f=ue((e.escape||S).source+"|"+f.source+"|"+(f===N?x:S).source+"|"+(e.evaluate||S).source+"|$","g");n.replace(f,function(t,e,r,o,f,c){return r||(r=o),l+=n.slice(a,c).replace(R,i),e&&(l+="'+__e("+e+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t
+}),l+="';",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(w,""):l).replace(j,"$1").replace(k,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=ne(r,"return "+l).apply(v,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},J.unescape=function(n){return null==n?"":oe(n).replace(qe,gt)},J.uniqueId=function(n){var t=++y;return oe(null==n?"":n)+t
+},J.all=Ot,J.any=Ft,J.detect=It,J.findWhere=It,J.foldl=Dt,J.foldr=$t,J.include=Ct,J.inject=Dt,Gt(function(){var n={};return h(J,function(t,e){J.prototype[e]||(n[e]=t)}),n}(),false),J.first=Bt,J.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=J.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:v;return p(n,Ie(0,u-r))},J.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=xt(n)),null==t||e?n?n[at(0,n.length-1)]:v:(n=Tt(n),n.length=Se(Ie(0,t),n.length),n)
+},J.take=Bt,J.head=Bt,h(J,function(n,t){var e="sample"!==t;J.prototype[t]||(J.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new Q(o,u):o})}),J.VERSION="2.4.1",J.prototype.chain=function(){return this.__chain__=true,this},J.prototype.toString=function(){return oe(this.__wrapped__)},J.prototype.value=Qt,J.prototype.valueOf=Qt,St(["join","pop","shift"],function(n){var t=ae[n];J.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);
+return n?new Q(e,n):e}}),St(["push","reverse","sort","unshift"],function(n){var t=ae[n];J.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),St(["concat","slice","splice"],function(n){var t=ae[n];J.prototype[n]=function(){return new Q(t.apply(this.__wrapped__,arguments),this.__chain__)}}),J}var v,h=[],g=[],y=0,m=+new Date+"",b=75,_=40,d=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",w=/\b__p\+='';/g,j=/\b(__p\+=)''\+/g,k=/(__e\(.*?\)|\b__t\))\+'';/g,x=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,C=/\w*$/,O=/^\s*function[ \n\r\t]+\w/,N=/<%=([\s\S]+?)%>/g,I=RegExp("^["+d+"]*0+(?=.$)"),S=/($^)/,E=/\bthis\b/,R=/['\n\r\t\u2028\u2029\\]/g,A="Array Boolean Date Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setTimeout".split(" "),D="[object Arguments]",$="[object Array]",T="[object Boolean]",F="[object Date]",B="[object Function]",W="[object Number]",q="[object Object]",z="[object RegExp]",P="[object String]",K={};
+K[B]=false,K[D]=K[$]=K[T]=K[F]=K[W]=K[q]=K[z]=K[P]=true;var L={leading:false,maxWait:0,trailing:false},M={configurable:false,enumerable:false,value:null,writable:false},V={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},U={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},G=V[typeof window]&&window||this,H=V[typeof exports]&&exports&&!exports.nodeType&&exports,J=V[typeof module]&&module&&!module.nodeType&&module,Q=J&&J.exports===H&&H,X=V[typeof global]&&global;!X||X.global!==X&&X.window!==X||(G=X);
+var Y=s();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(G._=Y, define(function(){return Y})):H&&J?Q?(J.exports=Y)._=Y:H._=Y:G._=Y}).call(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.underscore.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.underscore.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.underscore.js	(revision 533)
@@ -0,0 +1,4979 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
+ * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function() {
+
+  /** Used as a safe reference for `undefined` in pre ES5 environments */
+  var undefined;
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = {};
+
+  /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
+  var keyPrefix = +new Date + '';
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /** Used as a reference to the global object */
+  var root = (objectTypes[typeof window] && window) || this;
+
+  /** Detect free variable `exports` */
+  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+  /** Detect the popular CommonJS extension `module.exports` */
+  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+  /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
+  var freeGlobal = objectTypes[typeof global] && global;
+  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
+    root = freeGlobal;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The base implementation of `_.indexOf` without support for binary searches
+   * or `fromIndex` constraints.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {number} [fromIndex=0] The index to search from.
+   * @returns {number} Returns the index of the matched value or `-1`.
+   */
+  function baseIndexOf(array, value, fromIndex) {
+    var index = (fromIndex || 0) - 1,
+        length = array ? array.length : 0;
+
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` elements, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ac = a.criteria,
+        bc = b.criteria,
+        index = -1,
+        length = ac.length;
+
+    while (++index < length) {
+      var value = ac[index],
+          other = bc[index];
+
+      if (value !== other) {
+        if (value > other || typeof value == 'undefined') {
+          return 1;
+        }
+        if (value < other || typeof other == 'undefined') {
+          return -1;
+        }
+      }
+    }
+    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+    // that causes it, under certain circumstances, to return the same value for
+    // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
+    //
+    // This also ensures a stable sort in V8 and other engines.
+    // See http://code.google.com/p/v8/issues/detail?id=90
+    return a.index - b.index;
+  }
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {string} match The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used instead of `Array#slice` to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|string} collection The collection to slice.
+   * @param {number} start The start index.
+   * @param {number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Used for `Array` method references.
+   *
+   * Normally `Array.prototype` would suffice, however, using an array literal
+   * avoids issues in Narwhal.
+   */
+  var arrayRef = [];
+
+  /** Used for native method references */
+  var objectProto = Object.prototype;
+
+  /** Used to restore the original `_` reference in `noConflict` */
+  var oldDash = root._;
+
+  /** Used to resolve the internal [[Class]] of values */
+  var toString = objectProto.toString;
+
+  /** Used to detect if a method is native */
+  var reNative = RegExp('^' +
+    String(toString)
+      .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+      .replace(/toString| for [^\]]+/g, '.*?') + '$'
+  );
+
+  /** Native method shortcuts */
+  var ceil = Math.ceil,
+      floor = Math.floor,
+      hasOwnProperty = objectProto.hasOwnProperty,
+      push = arrayRef.push,
+      propertyIsEnumerable = objectProto.propertyIsEnumerable;
+
+  /* Native method shortcuts for methods with the same name as other `lodash` methods */
+  var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
+      nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
+      nativeIsFinite = root.isFinite,
+      nativeIsNaN = root.isNaN,
+      nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
+      nativeMax = Math.max,
+      nativeMin = Math.min,
+      nativeRandom = Math.random;
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object which wraps the given value to enable intuitive
+   * method chaining.
+   *
+   * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+   * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+   * and `unshift`
+   *
+   * Chaining is supported in custom builds as long as the `value` method is
+   * implicitly or explicitly included in the build.
+   *
+   * The chainable wrapper functions are:
+   * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
+   * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
+   * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
+   * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
+   * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
+   * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
+   * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
+   * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
+   * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
+   * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
+   * and `zip`
+   *
+   * The non-chainable wrapper functions are:
+   * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
+   * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
+   * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
+   * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
+   * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
+   * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
+   * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
+   * `template`, `unescape`, `uniqueId`, and `value`
+   *
+   * The wrapper functions `first` and `last` return wrapped values when `n` is
+   * provided, otherwise they return unwrapped values.
+   *
+   * Explicit chaining can be enabled by using the `_.chain` method.
+   *
+   * @name _
+   * @constructor
+   * @category Chaining
+   * @param {*} value The value to wrap in a `lodash` instance.
+   * @returns {Object} Returns a `lodash` instance.
+   * @example
+   *
+   * var wrapped = _([1, 2, 3]);
+   *
+   * // returns an unwrapped value
+   * wrapped.reduce(function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * // returns a wrapped value
+   * var squares = wrapped.map(function(num) {
+   *   return num * num;
+   * });
+   *
+   * _.isArray(squares);
+   * // => false
+   *
+   * _.isArray(squares.value());
+   * // => true
+   */
+  function lodash(value) {
+    return (value instanceof lodash)
+      ? value
+      : new lodashWrapper(value);
+  }
+
+  /**
+   * A fast path for creating `lodash` wrapper objects.
+   *
+   * @private
+   * @param {*} value The value to wrap in a `lodash` instance.
+   * @param {boolean} chainAll A flag to enable chaining for all methods
+   * @returns {Object} Returns a `lodash` instance.
+   */
+  function lodashWrapper(value, chainAll) {
+    this.__chain__ = !!chainAll;
+    this.__wrapped__ = value;
+  }
+  // ensure `new lodashWrapper` is an instance of `lodash`
+  lodashWrapper.prototype = lodash.prototype;
+
+  /**
+   * An object used to flag environments features.
+   *
+   * @static
+   * @memberOf _
+   * @type Object
+   */
+  var support = {};
+
+  (function() {
+    var object = { '0': 1, 'length': 1 };
+
+    /**
+     * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.
+     *
+     * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+     * and `splice()` functions that fail to remove the last element, `value[0]`,
+     * of array-like objects even though the `length` property is set to `0`.
+     * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+     * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+     *
+     * @memberOf _.support
+     * @type boolean
+     */
+    support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);
+  }(1));
+
+  /**
+   * By default, the template delimiters used by Lo-Dash are similar to those in
+   * embedded Ruby (ERB). Change the following template settings to use alternative
+   * delimiters.
+   *
+   * @static
+   * @memberOf _
+   * @type Object
+   */
+  lodash.templateSettings = {
+
+    /**
+     * Used to detect `data` property values to be HTML-escaped.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'escape': /<%-([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect code to be evaluated.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'evaluate': /<%([\s\S]+?)%>/g,
+
+    /**
+     * Used to detect `data` property values to inject.
+     *
+     * @memberOf _.templateSettings
+     * @type RegExp
+     */
+    'interpolate': reInterpolate,
+
+    /**
+     * Used to reference the data object in the template text.
+     *
+     * @memberOf _.templateSettings
+     * @type string
+     */
+    'variable': ''
+  };
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The base implementation of `_.bind` that creates the bound function and
+   * sets its meta data.
+   *
+   * @private
+   * @param {Array} bindData The bind data array.
+   * @returns {Function} Returns the new bound function.
+   */
+  function baseBind(bindData) {
+    var func = bindData[0],
+        partialArgs = bindData[2],
+        thisArg = bindData[4];
+
+    function bound() {
+      // `Function#bind` spec
+      // http://es5.github.io/#x15.3.4.5
+      if (partialArgs) {
+        // avoid `arguments` object deoptimizations by using `slice` instead
+        // of `Array.prototype.slice.call` and not assigning `arguments` to a
+        // variable as a ternary expression
+        var args = slice(partialArgs);
+        push.apply(args, arguments);
+      }
+      // mimic the constructor's `return` behavior
+      // http://es5.github.io/#x13.2.2
+      if (this instanceof bound) {
+        // ensure `new bound` is an instance of `func`
+        var thisBinding = baseCreate(func.prototype),
+            result = func.apply(thisBinding, args || arguments);
+        return isObject(result) ? result : thisBinding;
+      }
+      return func.apply(thisArg, args || arguments);
+    }
+    return bound;
+  }
+
+  /**
+   * The base implementation of `_.create` without support for assigning
+   * properties to the created object.
+   *
+   * @private
+   * @param {Object} prototype The object to inherit from.
+   * @returns {Object} Returns the new object.
+   */
+  function baseCreate(prototype, properties) {
+    return isObject(prototype) ? nativeCreate(prototype) : {};
+  }
+  // fallback for browsers without `Object.create`
+  if (!nativeCreate) {
+    baseCreate = (function() {
+      function Object() {}
+      return function(prototype) {
+        if (isObject(prototype)) {
+          Object.prototype = prototype;
+          var result = new Object;
+          Object.prototype = null;
+        }
+        return result || root.Object();
+      };
+    }());
+  }
+
+  /**
+   * The base implementation of `_.createCallback` without support for creating
+   * "_.pluck" or "_.where" style callbacks.
+   *
+   * @private
+   * @param {*} [func=identity] The value to convert to a callback.
+   * @param {*} [thisArg] The `this` binding of the created callback.
+   * @param {number} [argCount] The number of arguments the callback accepts.
+   * @returns {Function} Returns a callback function.
+   */
+  function baseCreateCallback(func, thisArg, argCount) {
+    if (typeof func != 'function') {
+      return identity;
+    }
+    // exit early for no `thisArg` or already bound by `Function#bind`
+    if (typeof thisArg == 'undefined' || !('prototype' in func)) {
+      return func;
+    }
+    switch (argCount) {
+      case 1: return function(value) {
+        return func.call(thisArg, value);
+      };
+      case 2: return function(a, b) {
+        return func.call(thisArg, a, b);
+      };
+      case 3: return function(value, index, collection) {
+        return func.call(thisArg, value, index, collection);
+      };
+      case 4: return function(accumulator, value, index, collection) {
+        return func.call(thisArg, accumulator, value, index, collection);
+      };
+    }
+    return bind(func, thisArg);
+  }
+
+  /**
+   * The base implementation of `createWrapper` that creates the wrapper and
+   * sets its meta data.
+   *
+   * @private
+   * @param {Array} bindData The bind data array.
+   * @returns {Function} Returns the new function.
+   */
+  function baseCreateWrapper(bindData) {
+    var func = bindData[0],
+        bitmask = bindData[1],
+        partialArgs = bindData[2],
+        partialRightArgs = bindData[3],
+        thisArg = bindData[4],
+        arity = bindData[5];
+
+    var isBind = bitmask & 1,
+        isBindKey = bitmask & 2,
+        isCurry = bitmask & 4,
+        isCurryBound = bitmask & 8,
+        key = func;
+
+    function bound() {
+      var thisBinding = isBind ? thisArg : this;
+      if (partialArgs) {
+        var args = slice(partialArgs);
+        push.apply(args, arguments);
+      }
+      if (partialRightArgs || isCurry) {
+        args || (args = slice(arguments));
+        if (partialRightArgs) {
+          push.apply(args, partialRightArgs);
+        }
+        if (isCurry && args.length < arity) {
+          bitmask |= 16 & ~32;
+          return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
+        }
+      }
+      args || (args = arguments);
+      if (isBindKey) {
+        func = thisBinding[key];
+      }
+      if (this instanceof bound) {
+        thisBinding = baseCreate(func.prototype);
+        var result = func.apply(thisBinding, args);
+        return isObject(result) ? result : thisBinding;
+      }
+      return func.apply(thisBinding, args);
+    }
+    return bound;
+  }
+
+  /**
+   * The base implementation of `_.difference` that accepts a single array
+   * of values to exclude.
+   *
+   * @private
+   * @param {Array} array The array to process.
+   * @param {Array} [values] The array of values to exclude.
+   * @returns {Array} Returns a new array of filtered values.
+   */
+  function baseDifference(array, values) {
+    var index = -1,
+        indexOf = getIndexOf(),
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (indexOf(values, value) < 0) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * The base implementation of `_.flatten` without support for callback
+   * shorthands or `thisArg` binding.
+   *
+   * @private
+   * @param {Array} array The array to flatten.
+   * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+   * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
+   * @param {number} [fromIndex=0] The index to start from.
+   * @returns {Array} Returns a new flattened array.
+   */
+  function baseFlatten(array, isShallow, isStrict, fromIndex) {
+    var index = (fromIndex || 0) - 1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+
+      if (value && typeof value == 'object' && typeof value.length == 'number'
+          && (isArray(value) || isArguments(value))) {
+        // recursively flatten arrays (susceptible to call stack limits)
+        if (!isShallow) {
+          value = baseFlatten(value, isShallow, isStrict);
+        }
+        var valIndex = -1,
+            valLength = value.length,
+            resIndex = result.length;
+
+        result.length += valLength;
+        while (++valIndex < valLength) {
+          result[resIndex++] = value[valIndex];
+        }
+      } else if (!isStrict) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * The base implementation of `_.isEqual`, without support for `thisArg` binding,
+   * that allows partial "_.where" style comparisons.
+   *
+   * @private
+   * @param {*} a The value to compare.
+   * @param {*} b The other value to compare.
+   * @param {Function} [callback] The function to customize comparing values.
+   * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
+   * @param {Array} [stackA=[]] Tracks traversed `a` objects.
+   * @param {Array} [stackB=[]] Tracks traversed `b` objects.
+   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+   */
+  function baseIsEqual(a, b, stackA, stackB) {
+    if (a === b) {
+      return a !== 0 || (1 / a == 1 / b);
+    }
+    var type = typeof a,
+        otherType = typeof b;
+
+    if (a === a &&
+        !(a && objectTypes[type]) &&
+        !(b && objectTypes[otherType])) {
+      return false;
+    }
+    if (a == null || b == null) {
+      return a === b;
+    }
+    var className = toString.call(a),
+        otherClass = toString.call(b);
+
+    if (className != otherClass) {
+      return false;
+    }
+    switch (className) {
+      case boolClass:
+      case dateClass:
+        return +a == +b;
+
+      case numberClass:
+        return a != +a
+          ? b != +b
+          : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+      case regexpClass:
+      case stringClass:
+        return a == String(b);
+    }
+    var isArr = className == arrayClass;
+    if (!isArr) {
+      var aWrapped = a instanceof lodash,
+          bWrapped = b instanceof lodash;
+
+      if (aWrapped || bWrapped) {
+        return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, stackA, stackB);
+      }
+      if (className != objectClass) {
+        return false;
+      }
+      var ctorA = a.constructor,
+          ctorB = b.constructor;
+
+      if (ctorA != ctorB &&
+            !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
+            ('constructor' in a && 'constructor' in b)
+          ) {
+        return false;
+      }
+    }
+    stackA || (stackA = []);
+    stackB || (stackB = []);
+
+    var length = stackA.length;
+    while (length--) {
+      if (stackA[length] == a) {
+        return stackB[length] == b;
+      }
+    }
+    var result = true,
+        size = 0;
+
+    stackA.push(a);
+    stackB.push(b);
+
+    if (isArr) {
+      size = b.length;
+      result = size == a.length;
+
+      if (result) {
+        while (size--) {
+          if (!(result = baseIsEqual(a[size], b[size], stackA, stackB))) {
+            break;
+          }
+        }
+      }
+    }
+    else {
+      forIn(b, function(value, key, b) {
+        if (hasOwnProperty.call(b, key)) {
+          size++;
+          return !(result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, stackA, stackB)) && indicatorObject;
+        }
+      });
+
+      if (result) {
+        forIn(a, function(value, key, a) {
+          if (hasOwnProperty.call(a, key)) {
+            return !(result = --size > -1) && indicatorObject;
+          }
+        });
+      }
+    }
+    stackA.pop();
+    stackB.pop();
+    return result;
+  }
+
+  /**
+   * The base implementation of `_.random` without argument juggling or support
+   * for returning floating-point numbers.
+   *
+   * @private
+   * @param {number} min The minimum possible value.
+   * @param {number} max The maximum possible value.
+   * @returns {number} Returns a random number.
+   */
+  function baseRandom(min, max) {
+    return min + floor(nativeRandom() * (max - min + 1));
+  }
+
+  /**
+   * The base implementation of `_.uniq` without support for callback shorthands
+   * or `thisArg` binding.
+   *
+   * @private
+   * @param {Array} array The array to process.
+   * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+   * @param {Function} [callback] The function called per iteration.
+   * @returns {Array} Returns a duplicate-value-free array.
+   */
+  function baseUniq(array, isSorted, callback) {
+    var index = -1,
+        indexOf = getIndexOf(),
+        length = array ? array.length : 0,
+        result = [],
+        seen = callback ? [] : result;
+
+    while (++index < length) {
+      var value = array[index],
+          computed = callback ? callback(value, index, array) : value;
+
+      if (isSorted
+            ? !index || seen[seen.length - 1] !== computed
+            : indexOf(seen, computed) < 0
+          ) {
+        if (callback) {
+          seen.push(computed);
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates a function that aggregates a collection, creating an object composed
+   * of keys generated from the results of running each element of the collection
+   * through a callback. The given `setter` function sets the keys and values
+   * of the composed object.
+   *
+   * @private
+   * @param {Function} setter The setter function.
+   * @returns {Function} Returns the new aggregator function.
+   */
+  function createAggregator(setter) {
+    return function(collection, callback, thisArg) {
+      var result = {};
+      callback = createCallback(callback, thisArg, 3);
+
+      var index = -1,
+          length = collection ? collection.length : 0;
+
+      if (typeof length == 'number') {
+        while (++index < length) {
+          var value = collection[index];
+          setter(result, value, callback(value, index, collection), collection);
+        }
+      } else {
+        forOwn(collection, function(value, key, collection) {
+          setter(result, value, callback(value, key, collection), collection);
+        });
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that, when called, either curries or invokes `func`
+   * with an optional `this` binding and partially applied arguments.
+   *
+   * @private
+   * @param {Function|string} func The function or method name to reference.
+   * @param {number} bitmask The bitmask of method flags to compose.
+   *  The bitmask may be composed of the following flags:
+   *  1 - `_.bind`
+   *  2 - `_.bindKey`
+   *  4 - `_.curry`
+   *  8 - `_.curry` (bound)
+   *  16 - `_.partial`
+   *  32 - `_.partialRight`
+   * @param {Array} [partialArgs] An array of arguments to prepend to those
+   *  provided to the new function.
+   * @param {Array} [partialRightArgs] An array of arguments to append to those
+   *  provided to the new function.
+   * @param {*} [thisArg] The `this` binding of `func`.
+   * @param {number} [arity] The arity of `func`.
+   * @returns {Function} Returns the new function.
+   */
+  function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
+    var isBind = bitmask & 1,
+        isBindKey = bitmask & 2,
+        isCurry = bitmask & 4,
+        isCurryBound = bitmask & 8,
+        isPartial = bitmask & 16,
+        isPartialRight = bitmask & 32;
+
+    if (!isBindKey && !isFunction(func)) {
+      throw new TypeError;
+    }
+    if (isPartial && !partialArgs.length) {
+      bitmask &= ~16;
+      isPartial = partialArgs = false;
+    }
+    if (isPartialRight && !partialRightArgs.length) {
+      bitmask &= ~32;
+      isPartialRight = partialRightArgs = false;
+    }
+    // fast path for `_.bind`
+    var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
+    return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
+  }
+
+  /**
+   * Used by `escape` to convert characters to HTML entities.
+   *
+   * @private
+   * @param {string} match The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeHtmlChar(match) {
+    return htmlEscapes[match];
+  }
+
+  /**
+   * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+   * customized, this method returns the custom method, otherwise it returns
+   * the `baseIndexOf` function.
+   *
+   * @private
+   * @returns {Function} Returns the "indexOf" function.
+   */
+  function getIndexOf() {
+    var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
+    return result;
+  }
+
+  /**
+   * Checks if `value` is a native function.
+   *
+   * @private
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
+   */
+  function isNative(value) {
+    return typeof value == 'function' && reNative.test(value);
+  }
+
+  /**
+   * Used by `unescape` to convert HTML entities to characters.
+   *
+   * @private
+   * @param {string} match The matched character to unescape.
+   * @returns {string} Returns the unescaped character.
+   */
+  function unescapeHtmlChar(match) {
+    return htmlUnescapes[match];
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if `value` is an `arguments` object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+   * @example
+   *
+   * (function() { return _.isArguments(arguments); })(1, 2, 3);
+   * // => true
+   *
+   * _.isArguments([1, 2, 3]);
+   * // => false
+   */
+  function isArguments(value) {
+    return value && typeof value == 'object' && typeof value.length == 'number' &&
+      toString.call(value) == argsClass || false;
+  }
+  // fallback for browsers that can't detect `arguments` objects by [[Class]]
+  if (!isArguments(arguments)) {
+    isArguments = function(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false;
+    };
+  }
+
+  /**
+   * Checks if `value` is an array.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
+   * @example
+   *
+   * (function() { return _.isArray(arguments); })();
+   * // => false
+   *
+   * _.isArray([1, 2, 3]);
+   * // => true
+   */
+  var isArray = nativeIsArray || function(value) {
+    return value && typeof value == 'object' && typeof value.length == 'number' &&
+      toString.call(value) == arrayClass || false;
+  };
+
+  /**
+   * A fallback implementation of `Object.keys` which produces an array of the
+   * given object's own enumerable property names.
+   *
+   * @private
+   * @type Function
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns an array of property names.
+   */
+  var shimKeys = function(object) {
+    var index, iterable = object, result = [];
+    if (!iterable) return result;
+    if (!(objectTypes[typeof object])) return result;
+      for (index in iterable) {
+        if (hasOwnProperty.call(iterable, index)) {
+          result.push(index);
+        }
+      }
+    return result
+  };
+
+  /**
+   * Creates an array composed of the own enumerable property names of an object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns an array of property names.
+   * @example
+   *
+   * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
+   */
+  var keys = !nativeKeys ? shimKeys : function(object) {
+    if (!isObject(object)) {
+      return [];
+    }
+    return nativeKeys(object);
+  };
+
+  /**
+   * Used to convert characters to HTML entities:
+   *
+   * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+   * don't require escaping in HTML and have no special meaning unless they're part
+   * of a tag or an unquoted attribute value.
+   * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+   */
+  var htmlEscapes = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;'
+  };
+
+  /** Used to convert HTML entities to characters */
+  var htmlUnescapes = invert(htmlEscapes);
+
+  /** Used to match HTML entities and HTML characters */
+  var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
+      reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object. Subsequent sources will overwrite property assignments of previous
+   * sources. If a callback is provided it will be executed to produce the
+   * assigned values. The callback is bound to `thisArg` and invoked with two
+   * arguments; (objectValue, sourceValue).
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @alias extend
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {...Object} [source] The source objects.
+   * @param {Function} [callback] The function to customize assigning values.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
+   * // => { 'name': 'fred', 'employer': 'slate' }
+   *
+   * var defaults = _.partialRight(_.assign, function(a, b) {
+   *   return typeof a == 'undefined' ? b : a;
+   * });
+   *
+   * var object = { 'name': 'barney' };
+   * defaults(object, { 'name': 'fred', 'employer': 'slate' });
+   * // => { 'name': 'barney', 'employer': 'slate' }
+   */
+  function assign(object) {
+    if (!object) {
+      return object;
+    }
+    for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
+      var iterable = arguments[argsIndex];
+      if (iterable) {
+        for (var key in iterable) {
+          object[key] = iterable[key];
+        }
+      }
+    }
+    return object;
+  }
+
+  /**
+   * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
+   * be cloned, otherwise they will be assigned by reference. If a callback
+   * is provided it will be executed to produce the cloned values. If the
+   * callback returns `undefined` cloning will be handled by the method instead.
+   * The callback is bound to `thisArg` and invoked with one argument; (value).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to clone.
+   * @param {boolean} [isDeep=false] Specify a deep clone.
+   * @param {Function} [callback] The function to customize cloning values.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the cloned value.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * var shallow = _.clone(characters);
+   * shallow[0] === characters[0];
+   * // => true
+   *
+   * var deep = _.clone(characters, true);
+   * deep[0] === characters[0];
+   * // => false
+   *
+   * _.mixin({
+   *   'clone': _.partialRight(_.clone, function(value) {
+   *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+   *   })
+   * });
+   *
+   * var clone = _.clone(document.body);
+   * clone.childNodes.length;
+   * // => 0
+   */
+  function clone(value) {
+    return isObject(value)
+      ? (isArray(value) ? slice(value) : assign({}, value))
+      : value;
+  }
+
+  /**
+   * Assigns own enumerable properties of source object(s) to the destination
+   * object for all destination properties that resolve to `undefined`. Once a
+   * property is set, additional defaults of the same property will be ignored.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The destination object.
+   * @param {...Object} [source] The source objects.
+   * @param- {Object} [guard] Allows working with `_.reduce` without using its
+   *  `key` and `object` arguments as sources.
+   * @returns {Object} Returns the destination object.
+   * @example
+   *
+   * var object = { 'name': 'barney' };
+   * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
+   * // => { 'name': 'barney', 'employer': 'slate' }
+   */
+  function defaults(object) {
+    if (!object) {
+      return object;
+    }
+    for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
+      var iterable = arguments[argsIndex];
+      if (iterable) {
+        for (var key in iterable) {
+          if (typeof object[key] == 'undefined') {
+            object[key] = iterable[key];
+          }
+        }
+      }
+    }
+    return object;
+  }
+
+  /**
+   * Iterates over own and inherited enumerable properties of an object,
+   * executing the callback for each property. The callback is bound to `thisArg`
+   * and invoked with three arguments; (value, key, object). Callbacks may exit
+   * iteration early by explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * function Shape() {
+   *   this.x = 0;
+   *   this.y = 0;
+   * }
+   *
+   * Shape.prototype.move = function(x, y) {
+   *   this.x += x;
+   *   this.y += y;
+   * };
+   *
+   * _.forIn(new Shape, function(value, key) {
+   *   console.log(key);
+   * });
+   * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
+   */
+  var forIn = function(collection, callback) {
+    var index, iterable = collection, result = iterable;
+    if (!iterable) return result;
+    if (!objectTypes[typeof iterable]) return result;
+      for (index in iterable) {
+        if (callback(iterable[index], index, collection) === indicatorObject) return result;
+      }
+    return result
+  };
+
+  /**
+   * Iterates over own enumerable properties of an object, executing the callback
+   * for each property. The callback is bound to `thisArg` and invoked with three
+   * arguments; (value, key, object). Callbacks may exit iteration early by
+   * explicitly returning `false`.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Objects
+   * @param {Object} object The object to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+   *   console.log(key);
+   * });
+   * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
+   */
+  var forOwn = function(collection, callback) {
+    var index, iterable = collection, result = iterable;
+    if (!iterable) return result;
+    if (!objectTypes[typeof iterable]) return result;
+      for (index in iterable) {
+        if (hasOwnProperty.call(iterable, index)) {
+          if (callback(iterable[index], index, collection) === indicatorObject) return result;
+        }
+      }
+    return result
+  };
+
+  /**
+   * Creates a sorted array of property names of all enumerable properties,
+   * own and inherited, of `object` that have function values.
+   *
+   * @static
+   * @memberOf _
+   * @alias methods
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns an array of property names that have function values.
+   * @example
+   *
+   * _.functions(_);
+   * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+   */
+  function functions(object) {
+    var result = [];
+    forIn(object, function(value, key) {
+      if (isFunction(value)) {
+        result.push(key);
+      }
+    });
+    return result.sort();
+  }
+
+  /**
+   * Checks if the specified property name exists as a direct property of `object`,
+   * instead of an inherited property.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @param {string} key The name of the property to check.
+   * @returns {boolean} Returns `true` if key is a direct property, else `false`.
+   * @example
+   *
+   * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+   * // => true
+   */
+  function has(object, key) {
+    return object ? hasOwnProperty.call(object, key) : false;
+  }
+
+  /**
+   * Creates an object composed of the inverted keys and values of the given object.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to invert.
+   * @returns {Object} Returns the created inverted object.
+   * @example
+   *
+   * _.invert({ 'first': 'fred', 'second': 'barney' });
+   * // => { 'fred': 'first', 'barney': 'second' }
+   */
+  function invert(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      result[object[key]] = key;
+    }
+    return result;
+  }
+
+  /**
+   * Checks if `value` is a boolean value.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
+   * @example
+   *
+   * _.isBoolean(null);
+   * // => false
+   */
+  function isBoolean(value) {
+    return value === true || value === false ||
+      value && typeof value == 'object' && toString.call(value) == boolClass || false;
+  }
+
+  /**
+   * Checks if `value` is a date.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
+   * @example
+   *
+   * _.isDate(new Date);
+   * // => true
+   */
+  function isDate(value) {
+    return value && typeof value == 'object' && toString.call(value) == dateClass || false;
+  }
+
+  /**
+   * Checks if `value` is a DOM element.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
+   * @example
+   *
+   * _.isElement(document.body);
+   * // => true
+   */
+  function isElement(value) {
+    return value && value.nodeType === 1 || false;
+  }
+
+  /**
+   * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+   * length of `0` and objects with no own enumerable properties are considered
+   * "empty".
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Array|Object|string} value The value to inspect.
+   * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
+   * @example
+   *
+   * _.isEmpty([1, 2, 3]);
+   * // => false
+   *
+   * _.isEmpty({});
+   * // => true
+   *
+   * _.isEmpty('');
+   * // => true
+   */
+  function isEmpty(value) {
+    if (!value) {
+      return true;
+    }
+    if (isArray(value) || isString(value)) {
+      return !value.length;
+    }
+    for (var key in value) {
+      if (hasOwnProperty.call(value, key)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Performs a deep comparison between two values to determine if they are
+   * equivalent to each other. If a callback is provided it will be executed
+   * to compare values. If the callback returns `undefined` comparisons will
+   * be handled by the method instead. The callback is bound to `thisArg` and
+   * invoked with two arguments; (a, b).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} a The value to compare.
+   * @param {*} b The other value to compare.
+   * @param {Function} [callback] The function to customize comparing values.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+   * @example
+   *
+   * var object = { 'name': 'fred' };
+   * var copy = { 'name': 'fred' };
+   *
+   * object == copy;
+   * // => false
+   *
+   * _.isEqual(object, copy);
+   * // => true
+   *
+   * var words = ['hello', 'goodbye'];
+   * var otherWords = ['hi', 'goodbye'];
+   *
+   * _.isEqual(words, otherWords, function(a, b) {
+   *   var reGreet = /^(?:hello|hi)$/i,
+   *       aGreet = _.isString(a) && reGreet.test(a),
+   *       bGreet = _.isString(b) && reGreet.test(b);
+   *
+   *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+   * });
+   * // => true
+   */
+  function isEqual(a, b) {
+    return baseIsEqual(a, b);
+  }
+
+  /**
+   * Checks if `value` is, or can be coerced to, a finite number.
+   *
+   * Note: This is not the same as native `isFinite` which will return true for
+   * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
+   * @example
+   *
+   * _.isFinite(-101);
+   * // => true
+   *
+   * _.isFinite('10');
+   * // => true
+   *
+   * _.isFinite(true);
+   * // => false
+   *
+   * _.isFinite('');
+   * // => false
+   *
+   * _.isFinite(Infinity);
+   * // => false
+   */
+  function isFinite(value) {
+    return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+  }
+
+  /**
+   * Checks if `value` is a function.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
+   * @example
+   *
+   * _.isFunction(_);
+   * // => true
+   */
+  function isFunction(value) {
+    return typeof value == 'function';
+  }
+  // fallback for older versions of Chrome and Safari
+  if (isFunction(/x/)) {
+    isFunction = function(value) {
+      return typeof value == 'function' && toString.call(value) == funcClass;
+    };
+  }
+
+  /**
+   * Checks if `value` is the language type of Object.
+   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
+   * @example
+   *
+   * _.isObject({});
+   * // => true
+   *
+   * _.isObject([1, 2, 3]);
+   * // => true
+   *
+   * _.isObject(1);
+   * // => false
+   */
+  function isObject(value) {
+    // check if the value is the ECMAScript language type of Object
+    // http://es5.github.io/#x8
+    // and avoid a V8 bug
+    // http://code.google.com/p/v8/issues/detail?id=2291
+    return !!(value && objectTypes[typeof value]);
+  }
+
+  /**
+   * Checks if `value` is `NaN`.
+   *
+   * Note: This is not the same as native `isNaN` which will return `true` for
+   * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
+   * @example
+   *
+   * _.isNaN(NaN);
+   * // => true
+   *
+   * _.isNaN(new Number(NaN));
+   * // => true
+   *
+   * isNaN(undefined);
+   * // => true
+   *
+   * _.isNaN(undefined);
+   * // => false
+   */
+  function isNaN(value) {
+    // `NaN` as a primitive is the only value that is not equal to itself
+    // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+    return isNumber(value) && value != +value;
+  }
+
+  /**
+   * Checks if `value` is `null`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
+   * @example
+   *
+   * _.isNull(null);
+   * // => true
+   *
+   * _.isNull(undefined);
+   * // => false
+   */
+  function isNull(value) {
+    return value === null;
+  }
+
+  /**
+   * Checks if `value` is a number.
+   *
+   * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
+   * @example
+   *
+   * _.isNumber(8.4 * 5);
+   * // => true
+   */
+  function isNumber(value) {
+    return typeof value == 'number' ||
+      value && typeof value == 'object' && toString.call(value) == numberClass || false;
+  }
+
+  /**
+   * Checks if `value` is a regular expression.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
+   * @example
+   *
+   * _.isRegExp(/fred/);
+   * // => true
+   */
+  function isRegExp(value) {
+    return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false;
+  }
+
+  /**
+   * Checks if `value` is a string.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
+   * @example
+   *
+   * _.isString('fred');
+   * // => true
+   */
+  function isString(value) {
+    return typeof value == 'string' ||
+      value && typeof value == 'object' && toString.call(value) == stringClass || false;
+  }
+
+  /**
+   * Checks if `value` is `undefined`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
+   * @example
+   *
+   * _.isUndefined(void 0);
+   * // => true
+   */
+  function isUndefined(value) {
+    return typeof value == 'undefined';
+  }
+
+  /**
+   * Creates a shallow clone of `object` excluding the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a callback is provided it will be executed for each
+   * property of `object` omitting the properties the callback returns truey
+   * for. The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|...string|string[]} [callback] The properties to omit or the
+   *  function called per iteration.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object without the omitted properties.
+   * @example
+   *
+   * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
+   * // => { 'name': 'fred' }
+   *
+   * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
+   *   return typeof value == 'number';
+   * });
+   * // => { 'name': 'fred' }
+   */
+  function omit(object) {
+    var props = [];
+    forIn(object, function(value, key) {
+      props.push(key);
+    });
+    props = baseDifference(props, baseFlatten(arguments, true, false, 1));
+
+    var index = -1,
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      result[key] = object[key];
+    }
+    return result;
+  }
+
+  /**
+   * Creates a two dimensional array of an object's key-value pairs,
+   * i.e. `[[key1, value1], [key2, value2]]`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns new array of key-value pairs.
+   * @example
+   *
+   * _.pairs({ 'barney': 36, 'fred': 40 });
+   * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
+   */
+  function pairs(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      var key = props[index];
+      result[index] = [key, object[key]];
+    }
+    return result;
+  }
+
+  /**
+   * Creates a shallow clone of `object` composed of the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a callback is provided it will be executed for each
+   * property of `object` picking the properties the callback returns truey
+   * for. The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|...string|string[]} [callback] The function called per
+   *  iteration or property names to pick, specified as individual property
+   *  names or arrays of property names.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object composed of the picked properties.
+   * @example
+   *
+   * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
+   * // => { 'name': 'fred' }
+   *
+   * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
+   *   return key.charAt(0) != '_';
+   * });
+   * // => { 'name': 'fred' }
+   */
+  function pick(object) {
+    var index = -1,
+        props = baseFlatten(arguments, true, false, 1),
+        length = props.length,
+        result = {};
+
+    while (++index < length) {
+      var key = props[index];
+      if (key in object) {
+        result[key] = object[key];
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array composed of the own enumerable property values of `object`.
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The object to inspect.
+   * @returns {Array} Returns an array of property values.
+   * @example
+   *
+   * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => [1, 2, 3] (property order is not guaranteed across environments)
+   */
+  function values(object) {
+    var index = -1,
+        props = keys(object),
+        length = props.length,
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = object[props[index]];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Checks if a given value is present in a collection using strict equality
+   * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
+   * offset from the end of the collection.
+   *
+   * @static
+   * @memberOf _
+   * @alias include
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {*} target The value to check for.
+   * @param {number} [fromIndex=0] The index to search from.
+   * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
+   * @example
+   *
+   * _.contains([1, 2, 3], 1);
+   * // => true
+   *
+   * _.contains([1, 2, 3], 1, 2);
+   * // => false
+   *
+   * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
+   * // => true
+   *
+   * _.contains('pebbles', 'eb');
+   * // => true
+   */
+  function contains(collection, target) {
+    var indexOf = getIndexOf(),
+        length = collection ? collection.length : 0,
+        result = false;
+    if (length && typeof length == 'number') {
+      result = indexOf(collection, target) > -1;
+    } else {
+      forOwn(collection, function(value) {
+        return (result = value === target) && indicatorObject;
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Creates an object composed of keys generated from the results of running
+   * each element of `collection` through the callback. The corresponding value
+   * of each key is the number of times the key was returned by the callback.
+   * The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': 1, '6': 2 }
+   *
+   * _.countBy(['one', 'two', 'three'], 'length');
+   * // => { '3': 2, '5': 1 }
+   */
+  var countBy = createAggregator(function(result, value, key) {
+    (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+  });
+
+  /**
+   * Checks if the given callback returns truey value for **all** elements of
+   * a collection. The callback is bound to `thisArg` and invoked with three
+   * arguments; (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias all
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {boolean} Returns `true` if all elements passed the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.every([true, 1, null, 'yes']);
+   * // => false
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.every(characters, 'age');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.every(characters, { 'age': 36 });
+   * // => false
+   */
+  function every(collection, callback, thisArg) {
+    var result = true;
+    callback = createCallback(callback, thisArg, 3);
+
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    if (typeof length == 'number') {
+      while (++index < length) {
+        if (!(result = !!callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      forOwn(collection, function(value, index, collection) {
+        return !(result = !!callback(value, index, collection)) && indicatorObject;
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Iterates over elements of a collection, returning an array of all elements
+   * the callback returns truey for. The callback is bound to `thisArg` and
+   * invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias select
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that passed the callback check.
+   * @example
+   *
+   * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [2, 4, 6]
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36, 'blocked': false },
+   *   { 'name': 'fred',   'age': 40, 'blocked': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.filter(characters, 'blocked');
+   * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+   *
+   * // using "_.where" callback shorthand
+   * _.filter(characters, { 'age': 36 });
+   * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+   */
+  function filter(collection, callback, thisArg) {
+    var result = [];
+    callback = createCallback(callback, thisArg, 3);
+
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    if (typeof length == 'number') {
+      while (++index < length) {
+        var value = collection[index];
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      }
+    } else {
+      forOwn(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result.push(value);
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Iterates over elements of a collection, returning the first element that
+   * the callback returns truey for. The callback is bound to `thisArg` and
+   * invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias detect, findWhere
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the found element, else `undefined`.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'age': 36, 'blocked': false },
+   *   { 'name': 'fred',    'age': 40, 'blocked': true },
+   *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+   * ];
+   *
+   * _.find(characters, function(chr) {
+   *   return chr.age < 40;
+   * });
+   * // => { 'name': 'barney', 'age': 36, 'blocked': false }
+   *
+   * // using "_.where" callback shorthand
+   * _.find(characters, { 'age': 1 });
+   * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
+   *
+   * // using "_.pluck" callback shorthand
+   * _.find(characters, 'blocked');
+   * // => { 'name': 'fred', 'age': 40, 'blocked': true }
+   */
+  function find(collection, callback, thisArg) {
+    callback = createCallback(callback, thisArg, 3);
+
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    if (typeof length == 'number') {
+      while (++index < length) {
+        var value = collection[index];
+        if (callback(value, index, collection)) {
+          return value;
+        }
+      }
+    } else {
+      var result;
+      forOwn(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result = value;
+          return indicatorObject;
+        }
+      });
+      return result;
+    }
+  }
+
+  /**
+   * Examines each element in a `collection`, returning the first that
+   * has the given properties. When checking `properties`, this method
+   * performs a deep comparison between values to determine if they are
+   * equivalent to each other.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Object} properties The object of property values to filter by.
+   * @returns {*} Returns the found element, else `undefined`.
+   * @example
+   *
+   * var food = [
+   *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
+   *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },
+   *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' }
+   * ];
+   *
+   * _.findWhere(food, { 'type': 'vegetable' });
+   * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
+   */
+  function findWhere(object, properties) {
+    return where(object, properties, true);
+  }
+
+  /**
+   * Iterates over elements of a collection, executing the callback for each
+   * element. The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, index|key, collection). Callbacks may exit iteration early by
+   * explicitly returning `false`.
+   *
+   * Note: As with other "Collections" methods, objects with a `length` property
+   * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+   * may be used for object iteration.
+   *
+   * @static
+   * @memberOf _
+   * @alias each
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|string} Returns `collection`.
+   * @example
+   *
+   * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
+   * // => logs each number and returns '1,2,3'
+   *
+   * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+   * // => logs each number and returns the object (property order is not guaranteed across environments)
+   */
+  function forEach(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+    if (typeof length == 'number') {
+      while (++index < length) {
+        if (callback(collection[index], index, collection) === indicatorObject) {
+          break;
+        }
+      }
+    } else {
+      forOwn(collection, callback);
+    }
+  }
+
+  /**
+   * This method is like `_.forEach` except that it iterates over elements
+   * of a `collection` from right to left.
+   *
+   * @static
+   * @memberOf _
+   * @alias eachRight
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array|Object|string} Returns `collection`.
+   * @example
+   *
+   * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
+   * // => logs each number from right to left and returns '3,2,1'
+   */
+  function forEachRight(collection, callback) {
+    var length = collection ? collection.length : 0;
+    if (typeof length == 'number') {
+      while (length--) {
+        if (callback(collection[length], length, collection) === false) {
+          break;
+        }
+      }
+    } else {
+      var props = keys(collection);
+      length = props.length;
+      forOwn(collection, function(value, key, collection) {
+        key = props ? props[--length] : --length;
+        return callback(collection[key], key, collection) === false && indicatorObject;
+      });
+    }
+  }
+
+  /**
+   * Creates an object composed of keys generated from the results of running
+   * each element of a collection through the callback. The corresponding value
+   * of each key is an array of the elements responsible for generating the key.
+   * The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+   * // => { '4': [4.2], '6': [6.1, 6.4] }
+   *
+   * // using "_.pluck" callback shorthand
+   * _.groupBy(['one', 'two', 'three'], 'length');
+   * // => { '3': ['one', 'two'], '5': ['three'] }
+   */
+  var groupBy = createAggregator(function(result, value, key) {
+    (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+  });
+
+  /**
+   * Creates an object composed of keys generated from the results of running
+   * each element of the collection through the given callback. The corresponding
+   * value of each key is the last element responsible for generating the key.
+   * The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * var keys = [
+   *   { 'dir': 'left', 'code': 97 },
+   *   { 'dir': 'right', 'code': 100 }
+   * ];
+   *
+   * _.indexBy(keys, 'dir');
+   * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+   *
+   * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
+   * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+   *
+   * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
+   * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+   */
+  var indexBy = createAggregator(function(result, value, key) {
+    result[key] = value;
+  });
+
+  /**
+   * Invokes the method named by `methodName` on each element in the `collection`
+   * returning an array of the results of each invoked method. Additional arguments
+   * will be provided to each invoked method. If `methodName` is a function it
+   * will be invoked for, and `this` bound to, each element in the `collection`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|string} methodName The name of the method to invoke or
+   *  the function invoked per iteration.
+   * @param {...*} [arg] Arguments to invoke the method with.
+   * @returns {Array} Returns a new array of the results of each invoked method.
+   * @example
+   *
+   * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+   * // => [[1, 5, 7], [1, 2, 3]]
+   *
+   * _.invoke([123, 456], String.prototype.split, '');
+   * // => [['1', '2', '3'], ['4', '5', '6']]
+   */
+  function invoke(collection, methodName) {
+    var args = slice(arguments, 2),
+        index = -1,
+        isFunc = typeof methodName == 'function',
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+    });
+    return result;
+  }
+
+  /**
+   * Creates an array of values by running each element in the collection
+   * through the callback. The callback is bound to `thisArg` and invoked with
+   * three arguments; (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias collect
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of the results of each `callback` execution.
+   * @example
+   *
+   * _.map([1, 2, 3], function(num) { return num * 3; });
+   * // => [3, 6, 9]
+   *
+   * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+   * // => [3, 6, 9] (property order is not guaranteed across environments)
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.map(characters, 'name');
+   * // => ['barney', 'fred']
+   */
+  function map(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    callback = createCallback(callback, thisArg, 3);
+    if (typeof length == 'number') {
+      var result = Array(length);
+      while (++index < length) {
+        result[index] = callback(collection[index], index, collection);
+      }
+    } else {
+      result = [];
+      forOwn(collection, function(value, key, collection) {
+        result[++index] = callback(value, key, collection);
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the maximum value of a collection. If the collection is empty or
+   * falsey `-Infinity` is returned. If a callback is provided it will be executed
+   * for each value in the collection to generate the criterion by which the value
+   * is ranked. The callback is bound to `thisArg` and invoked with three
+   * arguments; (value, index, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the maximum value.
+   * @example
+   *
+   * _.max([4, 2, 8, 6]);
+   * // => 8
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * _.max(characters, function(chr) { return chr.age; });
+   * // => { 'name': 'fred', 'age': 40 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.max(characters, 'age');
+   * // => { 'name': 'fred', 'age': 40 };
+   */
+  function max(collection, callback, thisArg) {
+    var computed = -Infinity,
+        result = computed;
+
+    // allows working with functions like `_.map` without using
+    // their `index` argument as a callback
+    if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+      callback = null;
+    }
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    if (callback == null && typeof length == 'number') {
+      while (++index < length) {
+        var value = collection[index];
+        if (value > result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg, 3);
+
+      forEach(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current > computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the minimum value of a collection. If the collection is empty or
+   * falsey `Infinity` is returned. If a callback is provided it will be executed
+   * for each value in the collection to generate the criterion by which the value
+   * is ranked. The callback is bound to `thisArg` and invoked with three
+   * arguments; (value, index, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the minimum value.
+   * @example
+   *
+   * _.min([4, 2, 8, 6]);
+   * // => 2
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * _.min(characters, function(chr) { return chr.age; });
+   * // => { 'name': 'barney', 'age': 36 };
+   *
+   * // using "_.pluck" callback shorthand
+   * _.min(characters, 'age');
+   * // => { 'name': 'barney', 'age': 36 };
+   */
+  function min(collection, callback, thisArg) {
+    var computed = Infinity,
+        result = computed;
+
+    // allows working with functions like `_.map` without using
+    // their `index` argument as a callback
+    if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+      callback = null;
+    }
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    if (callback == null && typeof length == 'number') {
+      while (++index < length) {
+        var value = collection[index];
+        if (value < result) {
+          result = value;
+        }
+      }
+    } else {
+      callback = createCallback(callback, thisArg, 3);
+
+      forEach(collection, function(value, index, collection) {
+        var current = callback(value, index, collection);
+        if (current < computed) {
+          computed = current;
+          result = value;
+        }
+      });
+    }
+    return result;
+  }
+
+  /**
+   * Retrieves the value of a specified property from all elements in the collection.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {string} property The name of the property to pluck.
+   * @returns {Array} Returns a new array of property values.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * _.pluck(characters, 'name');
+   * // => ['barney', 'fred']
+   */
+  var pluck = map;
+
+  /**
+   * Reduces a collection to a value which is the accumulated result of running
+   * each element in the collection through the callback, where each successive
+   * callback execution consumes the return value of the previous execution. If
+   * `accumulator` is not provided the first element of the collection will be
+   * used as the initial `accumulator` value. The callback is bound to `thisArg`
+   * and invoked with four arguments; (accumulator, value, index|key, collection).
+   *
+   * @static
+   * @memberOf _
+   * @alias foldl, inject
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [accumulator] Initial value of the accumulator.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the accumulated value.
+   * @example
+   *
+   * var sum = _.reduce([1, 2, 3], function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+   *   result[key] = num * 3;
+   *   return result;
+   * }, {});
+   * // => { 'a': 3, 'b': 6, 'c': 9 }
+   */
+  function reduce(collection, callback, accumulator, thisArg) {
+    if (!collection) return accumulator;
+    var noaccum = arguments.length < 3;
+    callback = createCallback(callback, thisArg, 4);
+
+    var index = -1,
+        length = collection.length;
+
+    if (typeof length == 'number') {
+      if (noaccum) {
+        accumulator = collection[++index];
+      }
+      while (++index < length) {
+        accumulator = callback(accumulator, collection[index], index, collection);
+      }
+    } else {
+      forOwn(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection)
+      });
+    }
+    return accumulator;
+  }
+
+  /**
+   * This method is like `_.reduce` except that it iterates over elements
+   * of a `collection` from right to left.
+   *
+   * @static
+   * @memberOf _
+   * @alias foldr
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [accumulator] Initial value of the accumulator.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the accumulated value.
+   * @example
+   *
+   * var list = [[0, 1], [2, 3], [4, 5]];
+   * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+   * // => [4, 5, 2, 3, 0, 1]
+   */
+  function reduceRight(collection, callback, accumulator, thisArg) {
+    var noaccum = arguments.length < 3;
+    callback = createCallback(callback, thisArg, 4);
+    forEachRight(collection, function(value, index, collection) {
+      accumulator = noaccum
+        ? (noaccum = false, value)
+        : callback(accumulator, value, index, collection);
+    });
+    return accumulator;
+  }
+
+  /**
+   * The opposite of `_.filter` this method returns the elements of a
+   * collection that the callback does **not** return truey for.
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of elements that failed the callback check.
+   * @example
+   *
+   * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+   * // => [1, 3, 5]
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36, 'blocked': false },
+   *   { 'name': 'fred',   'age': 40, 'blocked': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.reject(characters, 'blocked');
+   * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+   *
+   * // using "_.where" callback shorthand
+   * _.reject(characters, { 'age': 36 });
+   * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+   */
+  function reject(collection, callback, thisArg) {
+    callback = createCallback(callback, thisArg, 3);
+    return filter(collection, function(value, index, collection) {
+      return !callback(value, index, collection);
+    });
+  }
+
+  /**
+   * Retrieves a random element or `n` random elements from a collection.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to sample.
+   * @param {number} [n] The number of elements to sample.
+   * @param- {Object} [guard] Allows working with functions like `_.map`
+   *  without using their `index` arguments as `n`.
+   * @returns {Array} Returns the random sample(s) of `collection`.
+   * @example
+   *
+   * _.sample([1, 2, 3, 4]);
+   * // => 2
+   *
+   * _.sample([1, 2, 3, 4], 2);
+   * // => [3, 1]
+   */
+  function sample(collection, n, guard) {
+    if (collection && typeof collection.length != 'number') {
+      collection = values(collection);
+    }
+    if (n == null || guard) {
+      return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
+    }
+    var result = shuffle(collection);
+    result.length = nativeMin(nativeMax(0, n), result.length);
+    return result;
+  }
+
+  /**
+   * Creates an array of shuffled values, using a version of the Fisher-Yates
+   * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to shuffle.
+   * @returns {Array} Returns a new shuffled collection.
+   * @example
+   *
+   * _.shuffle([1, 2, 3, 4, 5, 6]);
+   * // => [4, 1, 6, 3, 5, 2]
+   */
+  function shuffle(collection) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    forEach(collection, function(value) {
+      var rand = baseRandom(0, ++index);
+      result[index] = result[rand];
+      result[rand] = value;
+    });
+    return result;
+  }
+
+  /**
+   * Gets the size of the `collection` by returning `collection.length` for arrays
+   * and array-like objects or the number of own enumerable properties for objects.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to inspect.
+   * @returns {number} Returns `collection.length` or number of own enumerable properties.
+   * @example
+   *
+   * _.size([1, 2]);
+   * // => 2
+   *
+   * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+   * // => 3
+   *
+   * _.size('pebbles');
+   * // => 7
+   */
+  function size(collection) {
+    var length = collection ? collection.length : 0;
+    return typeof length == 'number' ? length : keys(collection).length;
+  }
+
+  /**
+   * Checks if the callback returns a truey value for **any** element of a
+   * collection. The function returns as soon as it finds a passing value and
+   * does not iterate over the entire collection. The callback is bound to
+   * `thisArg` and invoked with three arguments; (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias any
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {boolean} Returns `true` if any element passed the callback check,
+   *  else `false`.
+   * @example
+   *
+   * _.some([null, 0, 'yes', false], Boolean);
+   * // => true
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36, 'blocked': false },
+   *   { 'name': 'fred',   'age': 40, 'blocked': true }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.some(characters, 'blocked');
+   * // => true
+   *
+   * // using "_.where" callback shorthand
+   * _.some(characters, { 'age': 1 });
+   * // => false
+   */
+  function some(collection, callback, thisArg) {
+    var result;
+    callback = createCallback(callback, thisArg, 3);
+
+    var index = -1,
+        length = collection ? collection.length : 0;
+
+    if (typeof length == 'number') {
+      while (++index < length) {
+        if ((result = callback(collection[index], index, collection))) {
+          break;
+        }
+      }
+    } else {
+      forOwn(collection, function(value, index, collection) {
+        return (result = callback(value, index, collection)) && indicatorObject;
+      });
+    }
+    return !!result;
+  }
+
+  /**
+   * Creates an array of elements, sorted in ascending order by the results of
+   * running each element in a collection through the callback. This method
+   * performs a stable sort, that is, it will preserve the original sort order
+   * of equal elements. The callback is bound to `thisArg` and invoked with
+   * three arguments; (value, index|key, collection).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an array of property names is provided for `callback` the collection
+   * will be sorted by each property value.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Array|Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new array of sorted elements.
+   * @example
+   *
+   * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+   * // => [3, 1, 2]
+   *
+   * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+   * // => [3, 1, 2]
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'age': 36 },
+   *   { 'name': 'fred',    'age': 40 },
+   *   { 'name': 'barney',  'age': 26 },
+   *   { 'name': 'fred',    'age': 30 }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.map(_.sortBy(characters, 'age'), _.values);
+   * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
+   *
+   * // sorting by multiple properties
+   * _.map(_.sortBy(characters, ['name', 'age']), _.values);
+   * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
+   */
+  function sortBy(collection, callback, thisArg) {
+    var index = -1,
+        length = collection ? collection.length : 0,
+        result = Array(typeof length == 'number' ? length : 0);
+
+    callback = createCallback(callback, thisArg, 3);
+    forEach(collection, function(value, key, collection) {
+      result[++index] = {
+        'criteria': [callback(value, key, collection)],
+        'index': index,
+        'value': value
+      };
+    });
+
+    length = result.length;
+    result.sort(compareAscending);
+    while (length--) {
+      result[length] = result[length].value;
+    }
+    return result;
+  }
+
+  /**
+   * Converts the `collection` to an array.
+   *
+   * @static
+   * @memberOf _
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to convert.
+   * @returns {Array} Returns the new converted array.
+   * @example
+   *
+   * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+   * // => [2, 3, 4]
+   */
+  function toArray(collection) {
+    if (isArray(collection)) {
+      return slice(collection);
+    }
+    if (collection && typeof collection.length == 'number') {
+      return map(collection);
+    }
+    return values(collection);
+  }
+
+  /**
+   * Performs a deep comparison of each element in a `collection` to the given
+   * `properties` object, returning an array of all elements that have equivalent
+   * property values.
+   *
+   * @static
+   * @memberOf _
+   * @type Function
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Object} props The object of property values to filter by.
+   * @returns {Array} Returns a new array of elements that have the given properties.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
+   *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+   * ];
+   *
+   * _.where(characters, { 'age': 36 });
+   * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
+   *
+   * _.where(characters, { 'pets': ['dino'] });
+   * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
+   */
+  function where(collection, properties, first) {
+    return (first && isEmpty(properties))
+      ? undefined
+      : (first ? find : filter)(collection, properties);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates an array with all falsey values removed. The values `false`, `null`,
+   * `0`, `""`, `undefined`, and `NaN` are all falsey.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to compact.
+   * @returns {Array} Returns a new array of filtered values.
+   * @example
+   *
+   * _.compact([0, 1, false, 2, '', 3]);
+   * // => [1, 2, 3]
+   */
+  function compact(array) {
+    var index = -1,
+        length = array ? array.length : 0,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index];
+      if (value) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Creates an array excluding all values of the provided arrays using strict
+   * equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {...Array} [values] The arrays of values to exclude.
+   * @returns {Array} Returns a new array of filtered values.
+   * @example
+   *
+   * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+   * // => [1, 3, 4]
+   */
+  function difference(array) {
+    return baseDifference(array, baseFlatten(arguments, true, true, 1));
+  }
+
+  /**
+   * Gets the first element or first `n` elements of an array. If a callback
+   * is provided elements at the beginning of the array are returned as long
+   * as the callback returns truey. The callback is bound to `thisArg` and
+   * invoked with three arguments; (value, index, array).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias head, take
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|number|string} [callback] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is provided it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the first element(s) of `array`.
+   * @example
+   *
+   * _.first([1, 2, 3]);
+   * // => 1
+   *
+   * _.first([1, 2, 3], 2);
+   * // => [1, 2]
+   *
+   * _.first([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [1, 2]
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+   *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
+   *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.first(characters, 'blocked');
+   * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
+   * // => ['barney', 'fred']
+   */
+  function first(array, callback, thisArg) {
+    var n = 0,
+        length = array ? array.length : 0;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = -1;
+      callback = createCallback(callback, thisArg, 3);
+      while (++index < length && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = callback;
+      if (n == null || thisArg) {
+        return array ? array[0] : undefined;
+      }
+    }
+    return slice(array, 0, nativeMin(nativeMax(0, n), length));
+  }
+
+  /**
+   * Flattens a nested array (the nesting can be to any depth). If `isShallow`
+   * is truey, the array will only be flattened a single level. If a callback
+   * is provided each element of the array is passed through the callback before
+   * flattening. The callback is bound to `thisArg` and invoked with three
+   * arguments; (value, index, array).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to flatten.
+   * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a new flattened array.
+   * @example
+   *
+   * _.flatten([1, [2], [3, [[4]]]]);
+   * // => [1, 2, 3, 4];
+   *
+   * _.flatten([1, [2], [3, [[4]]]], true);
+   * // => [1, 2, 3, [[4]]];
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
+   *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.flatten(characters, 'pets');
+   * // => ['hoppy', 'baby puss', 'dino']
+   */
+  function flatten(array, isShallow) {
+    return baseFlatten(array, isShallow);
+  }
+
+  /**
+   * Gets the index at which the first occurrence of `value` is found using
+   * strict equality for comparisons, i.e. `===`. If the array is already sorted
+   * providing `true` for `fromIndex` will run a faster binary search.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+   *  to perform a binary search on a sorted array.
+   * @returns {number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 1
+   *
+   * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 4
+   *
+   * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+   * // => 2
+   */
+  function indexOf(array, value, fromIndex) {
+    if (typeof fromIndex == 'number') {
+      var length = array ? array.length : 0;
+      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
+    } else if (fromIndex) {
+      var index = sortedIndex(array, value);
+      return array[index] === value ? index : -1;
+    }
+    return baseIndexOf(array, value, fromIndex);
+  }
+
+  /**
+   * Gets all but the last element or last `n` elements of an array. If a
+   * callback is provided elements at the end of the array are excluded from
+   * the result as long as the callback returns truey. The callback is bound
+   * to `thisArg` and invoked with three arguments; (value, index, array).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|number|string} [callback=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is provided it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.initial([1, 2, 3]);
+   * // => [1, 2]
+   *
+   * _.initial([1, 2, 3], 2);
+   * // => [1]
+   *
+   * _.initial([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [1]
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+   *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+   *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.initial(characters, 'blocked');
+   * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
+   *
+   * // using "_.where" callback shorthand
+   * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
+   * // => ['barney', 'fred']
+   */
+  function initial(array, callback, thisArg) {
+    var n = 0,
+        length = array ? array.length : 0;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = length;
+      callback = createCallback(callback, thisArg, 3);
+      while (index-- && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : callback || n;
+    }
+    return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+  }
+
+  /**
+   * Creates an array of unique values present in all provided arrays using
+   * strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {...Array} [array] The arrays to inspect.
+   * @returns {Array} Returns an array of shared values.
+   * @example
+   *
+   * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+   * // => [1, 2]
+   */
+  function intersection() {
+    var args = [],
+        argsIndex = -1,
+        argsLength = arguments.length;
+
+    while (++argsIndex < argsLength) {
+      var value = arguments[argsIndex];
+       if (isArray(value) || isArguments(value)) {
+         args.push(value);
+       }
+    }
+    var array = args[0],
+        index = -1,
+        indexOf = getIndexOf(),
+        length = array ? array.length : 0,
+        result = [];
+
+    outer:
+    while (++index < length) {
+      value = array[index];
+      if (indexOf(result, value) < 0) {
+        var argsIndex = argsLength;
+        while (--argsIndex) {
+          if (indexOf(args[argsIndex], value) < 0) {
+            continue outer;
+          }
+        }
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Gets the last element or last `n` elements of an array. If a callback is
+   * provided elements at the end of the array are returned as long as the
+   * callback returns truey. The callback is bound to `thisArg` and invoked
+   * with three arguments; (value, index, array).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|number|string} [callback] The function called
+   *  per element or the number of elements to return. If a property name or
+   *  object is provided it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the last element(s) of `array`.
+   * @example
+   *
+   * _.last([1, 2, 3]);
+   * // => 3
+   *
+   * _.last([1, 2, 3], 2);
+   * // => [2, 3]
+   *
+   * _.last([1, 2, 3], function(num) {
+   *   return num > 1;
+   * });
+   * // => [2, 3]
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+   *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+   *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.pluck(_.last(characters, 'blocked'), 'name');
+   * // => ['fred', 'pebbles']
+   *
+   * // using "_.where" callback shorthand
+   * _.last(characters, { 'employer': 'na' });
+   * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+   */
+  function last(array, callback, thisArg) {
+    var n = 0,
+        length = array ? array.length : 0;
+
+    if (typeof callback != 'number' && callback != null) {
+      var index = length;
+      callback = createCallback(callback, thisArg, 3);
+      while (index-- && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = callback;
+      if (n == null || thisArg) {
+        return array ? array[length - 1] : undefined;
+      }
+    }
+    return slice(array, nativeMax(0, length - n));
+  }
+
+  /**
+   * Gets the index at which the last occurrence of `value` is found using strict
+   * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+   * as the offset from the end of the collection.
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {number} [fromIndex=array.length-1] The index to search from.
+   * @returns {number} Returns the index of the matched value or `-1`.
+   * @example
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+   * // => 4
+   *
+   * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+   * // => 1
+   */
+  function lastIndexOf(array, value, fromIndex) {
+    var index = array ? array.length : 0;
+    if (typeof fromIndex == 'number') {
+      index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+    }
+    while (index--) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Creates an array of numbers (positive and/or negative) progressing from
+   * `start` up to but not including `end`. If `start` is less than `stop` a
+   * zero-length range is created unless a negative `step` is specified.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {number} [start=0] The start of the range.
+   * @param {number} end The end of the range.
+   * @param {number} [step=1] The value to increment or decrement by.
+   * @returns {Array} Returns a new range array.
+   * @example
+   *
+   * _.range(4);
+   * // => [0, 1, 2, 3]
+   *
+   * _.range(1, 5);
+   * // => [1, 2, 3, 4]
+   *
+   * _.range(0, 20, 5);
+   * // => [0, 5, 10, 15]
+   *
+   * _.range(0, -4, -1);
+   * // => [0, -1, -2, -3]
+   *
+   * _.range(1, 4, 0);
+   * // => [1, 1, 1]
+   *
+   * _.range(0);
+   * // => []
+   */
+  function range(start, end, step) {
+    start = +start || 0;
+    step =  (+step || 1);
+
+    if (end == null) {
+      end = start;
+      start = 0;
+    }
+    // use `Array(length)` so engines like Chakra and V8 avoid slower modes
+    // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+    var index = -1,
+        length = nativeMax(0, ceil((end - start) / step)),
+        result = Array(length);
+
+    while (++index < length) {
+      result[index] = start;
+      start += step;
+    }
+    return result;
+  }
+
+  /**
+   * The opposite of `_.initial` this method gets all but the first element or
+   * first `n` elements of an array. If a callback function is provided elements
+   * at the beginning of the array are excluded from the result as long as the
+   * callback returns truey. The callback is bound to `thisArg` and invoked
+   * with three arguments; (value, index, array).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias drop, tail
+   * @category Arrays
+   * @param {Array} array The array to query.
+   * @param {Function|Object|number|string} [callback=1] The function called
+   *  per element or the number of elements to exclude. If a property name or
+   *  object is provided it will be used to create a "_.pluck" or "_.where"
+   *  style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a slice of `array`.
+   * @example
+   *
+   * _.rest([1, 2, 3]);
+   * // => [2, 3]
+   *
+   * _.rest([1, 2, 3], 2);
+   * // => [3]
+   *
+   * _.rest([1, 2, 3], function(num) {
+   *   return num < 3;
+   * });
+   * // => [3]
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+   *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
+   *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
+   * ];
+   *
+   * // using "_.pluck" callback shorthand
+   * _.pluck(_.rest(characters, 'blocked'), 'name');
+   * // => ['fred', 'pebbles']
+   *
+   * // using "_.where" callback shorthand
+   * _.rest(characters, { 'employer': 'slate' });
+   * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+   */
+  function rest(array, callback, thisArg) {
+    if (typeof callback != 'number' && callback != null) {
+      var n = 0,
+          index = -1,
+          length = array ? array.length : 0;
+
+      callback = createCallback(callback, thisArg, 3);
+      while (++index < length && callback(array[index], index, array)) {
+        n++;
+      }
+    } else {
+      n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+    }
+    return slice(array, n);
+  }
+
+  /**
+   * Uses a binary search to determine the smallest index at which a value
+   * should be inserted into a given sorted array in order to maintain the sort
+   * order of the array. If a callback is provided it will be executed for
+   * `value` and each element of `array` to compute their sort ranking. The
+   * callback is bound to `thisArg` and invoked with one argument; (value).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to inspect.
+   * @param {*} value The value to evaluate.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {number} Returns the index at which `value` should be inserted
+   *  into `array`.
+   * @example
+   *
+   * _.sortedIndex([20, 30, 50], 40);
+   * // => 2
+   *
+   * // using "_.pluck" callback shorthand
+   * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+   * // => 2
+   *
+   * var dict = {
+   *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+   * };
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return dict.wordToNumber[word];
+   * });
+   * // => 2
+   *
+   * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+   *   return this.wordToNumber[word];
+   * }, dict);
+   * // => 2
+   */
+  function sortedIndex(array, value, callback, thisArg) {
+    var low = 0,
+        high = array ? array.length : low;
+
+    // explicitly reference `identity` for better inlining in Firefox
+    callback = callback ? createCallback(callback, thisArg, 1) : identity;
+    value = callback(value);
+
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      (callback(array[mid]) < value)
+        ? low = mid + 1
+        : high = mid;
+    }
+    return low;
+  }
+
+  /**
+   * Creates an array of unique values, in order, of the provided arrays using
+   * strict equality for comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {...Array} [array] The arrays to inspect.
+   * @returns {Array} Returns an array of combined values.
+   * @example
+   *
+   * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+   * // => [1, 2, 3, 5, 4]
+   */
+  function union() {
+    return baseUniq(baseFlatten(arguments, true, true));
+  }
+
+  /**
+   * Creates a duplicate-value-free version of an array using strict equality
+   * for comparisons, i.e. `===`. If the array is sorted, providing
+   * `true` for `isSorted` will use a faster algorithm. If a callback is provided
+   * each element of `array` is passed through the callback before uniqueness
+   * is computed. The callback is bound to `thisArg` and invoked with three
+   * arguments; (value, index, array).
+   *
+   * If a property name is provided for `callback` the created "_.pluck" style
+   * callback will return the property value of the given element.
+   *
+   * If an object is provided for `callback` the created "_.where" style callback
+   * will return `true` for elements that have the properties of the given object,
+   * else `false`.
+   *
+   * @static
+   * @memberOf _
+   * @alias unique
+   * @category Arrays
+   * @param {Array} array The array to process.
+   * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+   * @param {Function|Object|string} [callback=identity] The function called
+   *  per iteration. If a property name or object is provided it will be used
+   *  to create a "_.pluck" or "_.where" style callback, respectively.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns a duplicate-value-free array.
+   * @example
+   *
+   * _.uniq([1, 2, 1, 3, 1]);
+   * // => [1, 2, 3]
+   *
+   * _.uniq([1, 1, 2, 2, 3], true);
+   * // => [1, 2, 3]
+   *
+   * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
+   * // => ['A', 'b', 'C']
+   *
+   * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+   * // => [1, 2.5, 3]
+   *
+   * // using "_.pluck" callback shorthand
+   * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+   * // => [{ 'x': 1 }, { 'x': 2 }]
+   */
+  function uniq(array, isSorted, callback, thisArg) {
+    // juggle arguments
+    if (typeof isSorted != 'boolean' && isSorted != null) {
+      thisArg = callback;
+      callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
+      isSorted = false;
+    }
+    if (callback != null) {
+      callback = createCallback(callback, thisArg, 3);
+    }
+    return baseUniq(array, isSorted, callback);
+  }
+
+  /**
+   * Creates an array excluding all provided values using strict equality for
+   * comparisons, i.e. `===`.
+   *
+   * @static
+   * @memberOf _
+   * @category Arrays
+   * @param {Array} array The array to filter.
+   * @param {...*} [value] The values to exclude.
+   * @returns {Array} Returns a new array of filtered values.
+   * @example
+   *
+   * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+   * // => [2, 3, 4]
+   */
+  function without(array) {
+    return baseDifference(array, slice(arguments, 1));
+  }
+
+  /**
+   * Creates an array of grouped elements, the first of which contains the first
+   * elements of the given arrays, the second of which contains the second
+   * elements of the given arrays, and so on.
+   *
+   * @static
+   * @memberOf _
+   * @alias unzip
+   * @category Arrays
+   * @param {...Array} [array] Arrays to process.
+   * @returns {Array} Returns a new array of grouped elements.
+   * @example
+   *
+   * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+   * // => [['fred', 30, true], ['barney', 40, false]]
+   */
+  function zip() {
+    var index = -1,
+        length = max(pluck(arguments, 'length')),
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = pluck(arguments, index);
+    }
+    return result;
+  }
+
+  /**
+   * Creates an object composed from arrays of `keys` and `values`. Provide
+   * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
+   * or two arrays, one of `keys` and one of corresponding `values`.
+   *
+   * @static
+   * @memberOf _
+   * @alias object
+   * @category Arrays
+   * @param {Array} keys The array of keys.
+   * @param {Array} [values=[]] The array of values.
+   * @returns {Object} Returns an object composed of the given keys and
+   *  corresponding values.
+   * @example
+   *
+   * _.zipObject(['fred', 'barney'], [30, 40]);
+   * // => { 'fred': 30, 'barney': 40 }
+   */
+  function zipObject(keys, values) {
+    var index = -1,
+        length = keys ? keys.length : 0,
+        result = {};
+
+    if (!values && length && !isArray(keys[0])) {
+      values = [];
+    }
+    while (++index < length) {
+      var key = keys[index];
+      if (values) {
+        result[key] = values[index];
+      } else if (key) {
+        result[key[0]] = key[1];
+      }
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a function that executes `func`, with  the `this` binding and
+   * arguments of the created function, only after being called `n` times.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {number} n The number of times the function must be called before
+   *  `func` is executed.
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var saves = ['profile', 'settings'];
+   *
+   * var done = _.after(saves.length, function() {
+   *   console.log('Done saving!');
+   * });
+   *
+   * _.forEach(saves, function(type) {
+   *   asyncSave({ 'type': type, 'complete': done });
+   * });
+   * // => logs 'Done saving!', after all saves have completed
+   */
+  function after(n, func) {
+    if (!isFunction(func)) {
+      throw new TypeError;
+    }
+    return function() {
+      if (--n < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with the `this`
+   * binding of `thisArg` and prepends any additional `bind` arguments to those
+   * provided to the bound function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to bind.
+   * @param {*} [thisArg] The `this` binding of `func`.
+   * @param {...*} [arg] Arguments to be partially applied.
+   * @returns {Function} Returns the new bound function.
+   * @example
+   *
+   * var func = function(greeting) {
+   *   return greeting + ' ' + this.name;
+   * };
+   *
+   * func = _.bind(func, { 'name': 'fred' }, 'hi');
+   * func();
+   * // => 'hi fred'
+   */
+  function bind(func, thisArg) {
+    return arguments.length > 2
+      ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
+      : createWrapper(func, 1, null, null, thisArg);
+  }
+
+  /**
+   * Binds methods of an object to the object itself, overwriting the existing
+   * method. Method names may be specified as individual arguments or as arrays
+   * of method names. If no method names are provided all the function properties
+   * of `object` will be bound.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Object} object The object to bind and assign the bound methods to.
+   * @param {...string} [methodName] The object method names to
+   *  bind, specified as individual method names or arrays of method names.
+   * @returns {Object} Returns `object`.
+   * @example
+   *
+   * var view = {
+   *   'label': 'docs',
+   *   'onClick': function() { console.log('clicked ' + this.label); }
+   * };
+   *
+   * _.bindAll(view);
+   * jQuery('#docs').on('click', view.onClick);
+   * // => logs 'clicked docs', when the button is clicked
+   */
+  function bindAll(object) {
+    var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
+        index = -1,
+        length = funcs.length;
+
+    while (++index < length) {
+      var key = funcs[index];
+      object[key] = createWrapper(object[key], 1, null, null, object);
+    }
+    return object;
+  }
+
+  /**
+   * Creates a function that is the composition of the provided functions,
+   * where each function consumes the return value of the function that follows.
+   * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+   * Each function is executed with the `this` binding of the composed function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {...Function} [func] Functions to compose.
+   * @returns {Function} Returns the new composed function.
+   * @example
+   *
+   * var realNameMap = {
+   *   'pebbles': 'penelope'
+   * };
+   *
+   * var format = function(name) {
+   *   name = realNameMap[name.toLowerCase()] || name;
+   *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
+   * };
+   *
+   * var greet = function(formatted) {
+   *   return 'Hiya ' + formatted + '!';
+   * };
+   *
+   * var welcome = _.compose(greet, format);
+   * welcome('pebbles');
+   * // => 'Hiya Penelope!'
+   */
+  function compose() {
+    var funcs = arguments,
+        length = funcs.length;
+
+    while (length--) {
+      if (!isFunction(funcs[length])) {
+        throw new TypeError;
+      }
+    }
+    return function() {
+      var args = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        args = [funcs[length].apply(this, args)];
+      }
+      return args[0];
+    };
+  }
+
+  /**
+   * Creates a function that will delay the execution of `func` until after
+   * `wait` milliseconds have elapsed since the last time it was invoked.
+   * Provide an options object to indicate that `func` should be invoked on
+   * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
+   * to the debounced function will return the result of the last `func` call.
+   *
+   * Note: If `leading` and `trailing` options are `true` `func` will be called
+   * on the trailing edge of the timeout only if the the debounced function is
+   * invoked more than once during the `wait` timeout.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to debounce.
+   * @param {number} wait The number of milliseconds to delay.
+   * @param {Object} [options] The options object.
+   * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
+   * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
+   * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+   * @returns {Function} Returns the new debounced function.
+   * @example
+   *
+   * // avoid costly calculations while the window size is in flux
+   * var lazyLayout = _.debounce(calculateLayout, 150);
+   * jQuery(window).on('resize', lazyLayout);
+   *
+   * // execute `sendMail` when the click event is fired, debouncing subsequent calls
+   * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+   *   'leading': true,
+   *   'trailing': false
+   * });
+   *
+   * // ensure `batchLog` is executed once after 1 second of debounced calls
+   * var source = new EventSource('/stream');
+   * source.addEventListener('message', _.debounce(batchLog, 250, {
+   *   'maxWait': 1000
+   * }, false);
+   */
+  function debounce(func, wait, options) {
+    var args,
+        maxTimeoutId,
+        result,
+        stamp,
+        thisArg,
+        timeoutId,
+        trailingCall,
+        lastCalled = 0,
+        maxWait = false,
+        trailing = true;
+
+    if (!isFunction(func)) {
+      throw new TypeError;
+    }
+    wait = nativeMax(0, wait) || 0;
+    if (options === true) {
+      var leading = true;
+      trailing = false;
+    } else if (isObject(options)) {
+      leading = options.leading;
+      maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
+      trailing = 'trailing' in options ? options.trailing : trailing;
+    }
+    var delayed = function() {
+      var remaining = wait - (now() - stamp);
+      if (remaining <= 0) {
+        if (maxTimeoutId) {
+          clearTimeout(maxTimeoutId);
+        }
+        var isCalled = trailingCall;
+        maxTimeoutId = timeoutId = trailingCall = undefined;
+        if (isCalled) {
+          lastCalled = now();
+          result = func.apply(thisArg, args);
+          if (!timeoutId && !maxTimeoutId) {
+            args = thisArg = null;
+          }
+        }
+      } else {
+        timeoutId = setTimeout(delayed, remaining);
+      }
+    };
+
+    var maxDelayed = function() {
+      if (timeoutId) {
+        clearTimeout(timeoutId);
+      }
+      maxTimeoutId = timeoutId = trailingCall = undefined;
+      if (trailing || (maxWait !== wait)) {
+        lastCalled = now();
+        result = func.apply(thisArg, args);
+        if (!timeoutId && !maxTimeoutId) {
+          args = thisArg = null;
+        }
+      }
+    };
+
+    return function() {
+      args = arguments;
+      stamp = now();
+      thisArg = this;
+      trailingCall = trailing && (timeoutId || !leading);
+
+      if (maxWait === false) {
+        var leadingCall = leading && !timeoutId;
+      } else {
+        if (!maxTimeoutId && !leading) {
+          lastCalled = stamp;
+        }
+        var remaining = maxWait - (stamp - lastCalled),
+            isCalled = remaining <= 0;
+
+        if (isCalled) {
+          if (maxTimeoutId) {
+            maxTimeoutId = clearTimeout(maxTimeoutId);
+          }
+          lastCalled = stamp;
+          result = func.apply(thisArg, args);
+        }
+        else if (!maxTimeoutId) {
+          maxTimeoutId = setTimeout(maxDelayed, remaining);
+        }
+      }
+      if (isCalled && timeoutId) {
+        timeoutId = clearTimeout(timeoutId);
+      }
+      else if (!timeoutId && wait !== maxWait) {
+        timeoutId = setTimeout(delayed, wait);
+      }
+      if (leadingCall) {
+        isCalled = true;
+        result = func.apply(thisArg, args);
+      }
+      if (isCalled && !timeoutId && !maxTimeoutId) {
+        args = thisArg = null;
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Defers executing the `func` function until the current call stack has cleared.
+   * Additional arguments will be provided to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to defer.
+   * @param {...*} [arg] Arguments to invoke the function with.
+   * @returns {number} Returns the timer id.
+   * @example
+   *
+   * _.defer(function(text) { console.log(text); }, 'deferred');
+   * // logs 'deferred' after one or more milliseconds
+   */
+  function defer(func) {
+    if (!isFunction(func)) {
+      throw new TypeError;
+    }
+    var args = slice(arguments, 1);
+    return setTimeout(function() { func.apply(undefined, args); }, 1);
+  }
+
+  /**
+   * Executes the `func` function after `wait` milliseconds. Additional arguments
+   * will be provided to `func` when it is invoked.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to delay.
+   * @param {number} wait The number of milliseconds to delay execution.
+   * @param {...*} [arg] Arguments to invoke the function with.
+   * @returns {number} Returns the timer id.
+   * @example
+   *
+   * _.delay(function(text) { console.log(text); }, 1000, 'later');
+   * // => logs 'later' after one second
+   */
+  function delay(func, wait) {
+    if (!isFunction(func)) {
+      throw new TypeError;
+    }
+    var args = slice(arguments, 2);
+    return setTimeout(function() { func.apply(undefined, args); }, wait);
+  }
+
+  /**
+   * Creates a function that memoizes the result of `func`. If `resolver` is
+   * provided it will be used to determine the cache key for storing the result
+   * based on the arguments provided to the memoized function. By default, the
+   * first argument provided to the memoized function is used as the cache key.
+   * The `func` is executed with the `this` binding of the memoized function.
+   * The result cache is exposed as the `cache` property on the memoized function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to have its output memoized.
+   * @param {Function} [resolver] A function used to resolve the cache key.
+   * @returns {Function} Returns the new memoizing function.
+   * @example
+   *
+   * var fibonacci = _.memoize(function(n) {
+   *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+   * });
+   *
+   * fibonacci(9)
+   * // => 34
+   *
+   * var data = {
+   *   'fred': { 'name': 'fred', 'age': 40 },
+   *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+   * };
+   *
+   * // modifying the result cache
+   * var get = _.memoize(function(name) { return data[name]; }, _.identity);
+   * get('pebbles');
+   * // => { 'name': 'pebbles', 'age': 1 }
+   *
+   * get.cache.pebbles.name = 'penelope';
+   * get('pebbles');
+   * // => { 'name': 'penelope', 'age': 1 }
+   */
+  function memoize(func, resolver) {
+    var cache = {};
+    return function() {
+      var key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
+      return hasOwnProperty.call(cache, key)
+        ? cache[key]
+        : (cache[key] = func.apply(this, arguments));
+    };
+  }
+
+  /**
+   * Creates a function that is restricted to execute `func` once. Repeat calls to
+   * the function will return the value of the first call. The `func` is executed
+   * with the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to restrict.
+   * @returns {Function} Returns the new restricted function.
+   * @example
+   *
+   * var initialize = _.once(createApplication);
+   * initialize();
+   * initialize();
+   * // `initialize` executes `createApplication` once
+   */
+  function once(func) {
+    var ran,
+        result;
+
+    if (!isFunction(func)) {
+      throw new TypeError;
+    }
+    return function() {
+      if (ran) {
+        return result;
+      }
+      ran = true;
+      result = func.apply(this, arguments);
+
+      // clear the `func` variable so the function may be garbage collected
+      func = null;
+      return result;
+    };
+  }
+
+  /**
+   * Creates a function that, when called, invokes `func` with any additional
+   * `partial` arguments prepended to those provided to the new function. This
+   * method is similar to `_.bind` except it does **not** alter the `this` binding.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to partially apply arguments to.
+   * @param {...*} [arg] Arguments to be partially applied.
+   * @returns {Function} Returns the new partially applied function.
+   * @example
+   *
+   * var greet = function(greeting, name) { return greeting + ' ' + name; };
+   * var hi = _.partial(greet, 'hi');
+   * hi('fred');
+   * // => 'hi fred'
+   */
+  function partial(func) {
+    return createWrapper(func, 16, slice(arguments, 1));
+  }
+
+  /**
+   * Creates a function that, when executed, will only call the `func` function
+   * at most once per every `wait` milliseconds. Provide an options object to
+   * indicate that `func` should be invoked on the leading and/or trailing edge
+   * of the `wait` timeout. Subsequent calls to the throttled function will
+   * return the result of the last `func` call.
+   *
+   * Note: If `leading` and `trailing` options are `true` `func` will be called
+   * on the trailing edge of the timeout only if the the throttled function is
+   * invoked more than once during the `wait` timeout.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {Function} func The function to throttle.
+   * @param {number} wait The number of milliseconds to throttle executions to.
+   * @param {Object} [options] The options object.
+   * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
+   * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+   * @returns {Function} Returns the new throttled function.
+   * @example
+   *
+   * // avoid excessively updating the position while scrolling
+   * var throttled = _.throttle(updatePosition, 100);
+   * jQuery(window).on('scroll', throttled);
+   *
+   * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
+   * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+   *   'trailing': false
+   * }));
+   */
+  function throttle(func, wait, options) {
+    var leading = true,
+        trailing = true;
+
+    if (!isFunction(func)) {
+      throw new TypeError;
+    }
+    if (options === false) {
+      leading = false;
+    } else if (isObject(options)) {
+      leading = 'leading' in options ? options.leading : leading;
+      trailing = 'trailing' in options ? options.trailing : trailing;
+    }
+    options = {};
+    options.leading = leading;
+    options.maxWait = wait;
+    options.trailing = trailing;
+
+    return debounce(func, wait, options);
+  }
+
+  /**
+   * Creates a function that provides `value` to the wrapper function as its
+   * first argument. Additional arguments provided to the function are appended
+   * to those provided to the wrapper function. The wrapper is executed with
+   * the `this` binding of the created function.
+   *
+   * @static
+   * @memberOf _
+   * @category Functions
+   * @param {*} value The value to wrap.
+   * @param {Function} wrapper The wrapper function.
+   * @returns {Function} Returns the new function.
+   * @example
+   *
+   * var p = _.wrap(_.escape, function(func, text) {
+   *   return '<p>' + func(text) + '</p>';
+   * });
+   *
+   * p('Fred, Wilma, & Pebbles');
+   * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
+   */
+  function wrap(value, wrapper) {
+    return createWrapper(wrapper, 16, [value]);
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Produces a callback bound to an optional `thisArg`. If `func` is a property
+   * name the created callback will return the property value for a given element.
+   * If `func` is an object the created callback will return `true` for elements
+   * that contain the equivalent object properties, otherwise it will return `false`.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {*} [func=identity] The value to convert to a callback.
+   * @param {*} [thisArg] The `this` binding of the created callback.
+   * @param {number} [argCount] The number of arguments the callback accepts.
+   * @returns {Function} Returns a callback function.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * // wrap to create custom callback shorthands
+   * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
+   *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
+   *   return !match ? func(callback, thisArg) : function(object) {
+   *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
+   *   };
+   * });
+   *
+   * _.filter(characters, 'age__gt38');
+   * // => [{ 'name': 'fred', 'age': 40 }]
+   */
+  function createCallback(func, thisArg, argCount) {
+    var type = typeof func;
+    if (func == null || type == 'function') {
+      return baseCreateCallback(func, thisArg, argCount);
+    }
+    // handle "_.pluck" style callback shorthands
+    if (type != 'object') {
+      return property(func);
+    }
+    var props = keys(func);
+    return function(object) {
+      var length = props.length,
+          result = false;
+
+      while (length--) {
+        if (!(result = object[props[length]] === func[props[length]])) {
+          break;
+        }
+      }
+      return result;
+    };
+  }
+
+  /**
+   * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+   * corresponding HTML entities.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {string} string The string to escape.
+   * @returns {string} Returns the escaped string.
+   * @example
+   *
+   * _.escape('Fred, Wilma, & Pebbles');
+   * // => 'Fred, Wilma, &amp; Pebbles'
+   */
+  function escape(string) {
+    return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
+  }
+
+  /**
+   * This method returns the first argument provided to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {*} value Any value.
+   * @returns {*} Returns `value`.
+   * @example
+   *
+   * var object = { 'name': 'fred' };
+   * _.identity(object) === object;
+   * // => true
+   */
+  function identity(value) {
+    return value;
+  }
+
+  /**
+   * Adds function properties of a source object to the destination object.
+   * If `object` is a function methods will be added to its prototype as well.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Function|Object} [object=lodash] object The destination object.
+   * @param {Object} source The object of functions to add.
+   * @param {Object} [options] The options object.
+   * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
+   * @example
+   *
+   * function capitalize(string) {
+   *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+   * }
+   *
+   * _.mixin({ 'capitalize': capitalize });
+   * _.capitalize('fred');
+   * // => 'Fred'
+   *
+   * _('fred').capitalize().value();
+   * // => 'Fred'
+   *
+   * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
+   * _('fred').capitalize();
+   * // => 'Fred'
+   */
+  function mixin(object) {
+    forEach(functions(object), function(methodName) {
+      var func = lodash[methodName] = object[methodName];
+
+      lodash.prototype[methodName] = function() {
+        var args = [this.__wrapped__];
+        push.apply(args, arguments);
+
+        var result = func.apply(lodash, args);
+        return this.__chain__
+          ? new lodashWrapper(result, true)
+          : result;
+      };
+    });
+  }
+
+  /**
+   * Reverts the '_' variable to its previous value and returns a reference to
+   * the `lodash` function.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @returns {Function} Returns the `lodash` function.
+   * @example
+   *
+   * var lodash = _.noConflict();
+   */
+  function noConflict() {
+    root._ = oldDash;
+    return this;
+  }
+
+  /**
+   * A no-operation function.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @example
+   *
+   * var object = { 'name': 'fred' };
+   * _.noop(object) === undefined;
+   * // => true
+   */
+  function noop() {
+    // no operation performed
+  }
+
+  /**
+   * Gets the number of milliseconds that have elapsed since the Unix epoch
+   * (1 January 1970 00:00:00 UTC).
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @example
+   *
+   * var stamp = _.now();
+   * _.defer(function() { console.log(_.now() - stamp); });
+   * // => logs the number of milliseconds it took for the deferred function to be called
+   */
+  var now = isNative(now = Date.now) && now || function() {
+    return new Date().getTime();
+  };
+
+  /**
+   * Creates a "_.pluck" style function, which returns the `key` value of a
+   * given object.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {string} key The name of the property to retrieve.
+   * @returns {Function} Returns the new function.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'fred',   'age': 40 },
+   *   { 'name': 'barney', 'age': 36 }
+   * ];
+   *
+   * var getName = _.property('name');
+   *
+   * _.map(characters, getName);
+   * // => ['barney', 'fred']
+   *
+   * _.sortBy(characters, getName);
+   * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
+   */
+  function property(key) {
+    return function(object) {
+      return object[key];
+    };
+  }
+
+  /**
+   * Produces a random number between `min` and `max` (inclusive). If only one
+   * argument is provided a number between `0` and the given number will be
+   * returned. If `floating` is truey or either `min` or `max` are floats a
+   * floating-point number will be returned instead of an integer.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {number} [min=0] The minimum possible value.
+   * @param {number} [max=1] The maximum possible value.
+   * @param {boolean} [floating=false] Specify returning a floating-point number.
+   * @returns {number} Returns a random number.
+   * @example
+   *
+   * _.random(0, 5);
+   * // => an integer between 0 and 5
+   *
+   * _.random(5);
+   * // => also an integer between 0 and 5
+   *
+   * _.random(5, true);
+   * // => a floating-point number between 0 and 5
+   *
+   * _.random(1.2, 5.2);
+   * // => a floating-point number between 1.2 and 5.2
+   */
+  function random(min, max) {
+    if (min == null && max == null) {
+      max = 1;
+    }
+    min = +min || 0;
+    if (max == null) {
+      max = min;
+      min = 0;
+    } else {
+      max = +max || 0;
+    }
+    return min + floor(nativeRandom() * (max - min + 1));
+  }
+
+  /**
+   * Resolves the value of property `key` on `object`. If `key` is a function
+   * it will be invoked with the `this` binding of `object` and its result returned,
+   * else the property value is returned. If `object` is falsey then `undefined`
+   * is returned.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} object The object to inspect.
+   * @param {string} key The name of the property to resolve.
+   * @returns {*} Returns the resolved value.
+   * @example
+   *
+   * var object = {
+   *   'cheese': 'crumpets',
+   *   'stuff': function() {
+   *     return 'nonsense';
+   *   }
+   * };
+   *
+   * _.result(object, 'cheese');
+   * // => 'crumpets'
+   *
+   * _.result(object, 'stuff');
+   * // => 'nonsense'
+   */
+  function result(object, key) {
+    if (object) {
+      var value = object[key];
+      return isFunction(value) ? object[key]() : value;
+    }
+  }
+
+  /**
+   * A micro-templating method that handles arbitrary delimiters, preserves
+   * whitespace, and correctly escapes quotes within interpolated code.
+   *
+   * Note: In the development build, `_.template` utilizes sourceURLs for easier
+   * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+   *
+   * For more information on precompiling templates see:
+   * http://lodash.com/custom-builds
+   *
+   * For more information on Chrome extension sandboxes see:
+   * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {string} text The template text.
+   * @param {Object} data The data object used to populate the text.
+   * @param {Object} [options] The options object.
+   * @param {RegExp} [options.escape] The "escape" delimiter.
+   * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+   * @param {Object} [options.imports] An object to import into the template as local variables.
+   * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+   * @param {string} [sourceURL] The sourceURL of the template's compiled source.
+   * @param {string} [variable] The data object variable name.
+   * @returns {Function|string} Returns a compiled function when no `data` object
+   *  is given, else it returns the interpolated text.
+   * @example
+   *
+   * // using the "interpolate" delimiter to create a compiled template
+   * var compiled = _.template('hello <%= name %>');
+   * compiled({ 'name': 'fred' });
+   * // => 'hello fred'
+   *
+   * // using the "escape" delimiter to escape HTML in data property values
+   * _.template('<b><%- value %></b>', { 'value': '<script>' });
+   * // => '<b>&lt;script&gt;</b>'
+   *
+   * // using the "evaluate" delimiter to generate HTML
+   * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
+   * _.template(list, { 'people': ['fred', 'barney'] });
+   * // => '<li>fred</li><li>barney</li>'
+   *
+   * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+   * _.template('hello ${ name }', { 'name': 'pebbles' });
+   * // => 'hello pebbles'
+   *
+   * // using the internal `print` function in "evaluate" delimiters
+   * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
+   * // => 'hello barney!'
+   *
+   * // using a custom template delimiters
+   * _.templateSettings = {
+   *   'interpolate': /{{([\s\S]+?)}}/g
+   * };
+   *
+   * _.template('hello {{ name }}!', { 'name': 'mustache' });
+   * // => 'hello mustache!'
+   *
+   * // using the `imports` option to import jQuery
+   * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
+   * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
+   * // => '<li>fred</li><li>barney</li>'
+   *
+   * // using the `sourceURL` option to specify a custom sourceURL for the template
+   * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+   * compiled(data);
+   * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+   *
+   * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+   * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+   * compiled.source;
+   * // => function(data) {
+   *   var __t, __p = '', __e = _.escape;
+   *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+   *   return __p;
+   * }
+   *
+   * // using the `source` property to inline compiled templates for meaningful
+   * // line numbers in error messages and a stack trace
+   * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+   *   var JST = {\
+   *     "main": ' + _.template(mainText).source + '\
+   *   };\
+   * ');
+   */
+  function template(text, data, options) {
+    var _ = lodash,
+        settings = _.templateSettings;
+
+    text = String(text || '');
+    options = defaults({}, options, settings);
+
+    var index = 0,
+        source = "__p += '",
+        variable = options.variable;
+
+    var reDelimiters = RegExp(
+      (options.escape || reNoMatch).source + '|' +
+      (options.interpolate || reNoMatch).source + '|' +
+      (options.evaluate || reNoMatch).source + '|$'
+    , 'g');
+
+    text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {
+      source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+      if (escapeValue) {
+        source += "' +\n_.escape(" + escapeValue + ") +\n'";
+      }
+      if (evaluateValue) {
+        source += "';\n" + evaluateValue + ";\n__p += '";
+      }
+      if (interpolateValue) {
+        source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+      }
+      index = offset + match.length;
+      return match;
+    });
+
+    source += "';\n";
+    if (!variable) {
+      variable = 'obj';
+      source = 'with (' + variable + ' || {}) {\n' + source + '\n}\n';
+    }
+    source = 'function(' + variable + ') {\n' +
+      "var __t, __p = '', __j = Array.prototype.join;\n" +
+      "function print() { __p += __j.call(arguments, '') }\n" +
+      source +
+      'return __p\n}';
+
+    try {
+      var result = Function('_', 'return ' + source)(_);
+    } catch(e) {
+      e.source = source;
+      throw e;
+    }
+    if (data) {
+      return result(data);
+    }
+    result.source = source;
+    return result;
+  }
+
+  /**
+   * Executes the callback `n` times, returning an array of the results
+   * of each callback execution. The callback is bound to `thisArg` and invoked
+   * with one argument; (index).
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {number} n The number of times to execute the callback.
+   * @param {Function} callback The function called per iteration.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Array} Returns an array of the results of each `callback` execution.
+   * @example
+   *
+   * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+   * // => [3, 6, 4]
+   *
+   * _.times(3, function(n) { mage.castSpell(n); });
+   * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+   *
+   * _.times(3, function(n) { this.cast(n); }, mage);
+   * // => also calls `mage.castSpell(n)` three times
+   */
+  function times(n, callback, thisArg) {
+    n = (n = +n) > -1 ? n : 0;
+    var index = -1,
+        result = Array(n);
+
+    callback = baseCreateCallback(callback, thisArg, 1);
+    while (++index < n) {
+      result[index] = callback(index);
+    }
+    return result;
+  }
+
+  /**
+   * The inverse of `_.escape` this method converts the HTML entities
+   * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+   * corresponding characters.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {string} string The string to unescape.
+   * @returns {string} Returns the unescaped string.
+   * @example
+   *
+   * _.unescape('Fred, Barney &amp; Pebbles');
+   * // => 'Fred, Barney & Pebbles'
+   */
+  function unescape(string) {
+    return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
+  }
+
+  /**
+   * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {string} [prefix] The value to prefix the ID with.
+   * @returns {string} Returns the unique ID.
+   * @example
+   *
+   * _.uniqueId('contact_');
+   * // => 'contact_104'
+   *
+   * _.uniqueId();
+   * // => '105'
+   */
+  function uniqueId(prefix) {
+    var id = ++idCounter + '';
+    return prefix ? prefix + id : id;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Creates a `lodash` object that wraps the given value with explicit
+   * method chaining enabled.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {*} value The value to wrap.
+   * @returns {Object} Returns the wrapper object.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney',  'age': 36 },
+   *   { 'name': 'fred',    'age': 40 },
+   *   { 'name': 'pebbles', 'age': 1 }
+   * ];
+   *
+   * var youngest = _.chain(characters)
+   *     .sortBy('age')
+   *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
+   *     .first()
+   *     .value();
+   * // => 'pebbles is 1'
+   */
+  function chain(value) {
+    value = new lodashWrapper(value);
+    value.__chain__ = true;
+    return value;
+  }
+
+  /**
+   * Invokes `interceptor` with the `value` as the first argument and then
+   * returns `value`. The purpose of this method is to "tap into" a method
+   * chain in order to perform operations on intermediate results within
+   * the chain.
+   *
+   * @static
+   * @memberOf _
+   * @category Chaining
+   * @param {*} value The value to provide to `interceptor`.
+   * @param {Function} interceptor The function to invoke.
+   * @returns {*} Returns `value`.
+   * @example
+   *
+   * _([1, 2, 3, 4])
+   *  .tap(function(array) { array.pop(); })
+   *  .reverse()
+   *  .value();
+   * // => [3, 2, 1]
+   */
+  function tap(value, interceptor) {
+    interceptor(value);
+    return value;
+  }
+
+  /**
+   * Enables explicit method chaining on the wrapper object.
+   *
+   * @name chain
+   * @memberOf _
+   * @category Chaining
+   * @returns {*} Returns the wrapper object.
+   * @example
+   *
+   * var characters = [
+   *   { 'name': 'barney', 'age': 36 },
+   *   { 'name': 'fred',   'age': 40 }
+   * ];
+   *
+   * // without explicit chaining
+   * _(characters).first();
+   * // => { 'name': 'barney', 'age': 36 }
+   *
+   * // with explicit chaining
+   * _(characters).chain()
+   *   .first()
+   *   .pick('age')
+   *   .value();
+   * // => { 'age': 36 }
+   */
+  function wrapperChain() {
+    this.__chain__ = true;
+    return this;
+  }
+
+  /**
+   * Extracts the wrapped value.
+   *
+   * @name valueOf
+   * @memberOf _
+   * @alias value
+   * @category Chaining
+   * @returns {*} Returns the wrapped value.
+   * @example
+   *
+   * _([1, 2, 3]).valueOf();
+   * // => [1, 2, 3]
+   */
+  function wrapperValueOf() {
+    return this.__wrapped__;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return wrapped values when chaining
+  lodash.after = after;
+  lodash.bind = bind;
+  lodash.bindAll = bindAll;
+  lodash.chain = chain;
+  lodash.compact = compact;
+  lodash.compose = compose;
+  lodash.countBy = countBy;
+  lodash.debounce = debounce;
+  lodash.defaults = defaults;
+  lodash.defer = defer;
+  lodash.delay = delay;
+  lodash.difference = difference;
+  lodash.filter = filter;
+  lodash.flatten = flatten;
+  lodash.forEach = forEach;
+  lodash.functions = functions;
+  lodash.groupBy = groupBy;
+  lodash.indexBy = indexBy;
+  lodash.initial = initial;
+  lodash.intersection = intersection;
+  lodash.invert = invert;
+  lodash.invoke = invoke;
+  lodash.keys = keys;
+  lodash.map = map;
+  lodash.max = max;
+  lodash.memoize = memoize;
+  lodash.min = min;
+  lodash.omit = omit;
+  lodash.once = once;
+  lodash.pairs = pairs;
+  lodash.partial = partial;
+  lodash.pick = pick;
+  lodash.pluck = pluck;
+  lodash.range = range;
+  lodash.reject = reject;
+  lodash.rest = rest;
+  lodash.shuffle = shuffle;
+  lodash.sortBy = sortBy;
+  lodash.tap = tap;
+  lodash.throttle = throttle;
+  lodash.times = times;
+  lodash.toArray = toArray;
+  lodash.union = union;
+  lodash.uniq = uniq;
+  lodash.values = values;
+  lodash.where = where;
+  lodash.without = without;
+  lodash.wrap = wrap;
+  lodash.zip = zip;
+
+  // add aliases
+  lodash.collect = map;
+  lodash.drop = rest;
+  lodash.each = forEach;
+  lodash.extend = assign;
+  lodash.methods = functions;
+  lodash.object = zipObject;
+  lodash.select = filter;
+  lodash.tail = rest;
+  lodash.unique = uniq;
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions that return unwrapped values when chaining
+  lodash.clone = clone;
+  lodash.contains = contains;
+  lodash.escape = escape;
+  lodash.every = every;
+  lodash.find = find;
+  lodash.has = has;
+  lodash.identity = identity;
+  lodash.indexOf = indexOf;
+  lodash.isArguments = isArguments;
+  lodash.isArray = isArray;
+  lodash.isBoolean = isBoolean;
+  lodash.isDate = isDate;
+  lodash.isElement = isElement;
+  lodash.isEmpty = isEmpty;
+  lodash.isEqual = isEqual;
+  lodash.isFinite = isFinite;
+  lodash.isFunction = isFunction;
+  lodash.isNaN = isNaN;
+  lodash.isNull = isNull;
+  lodash.isNumber = isNumber;
+  lodash.isObject = isObject;
+  lodash.isRegExp = isRegExp;
+  lodash.isString = isString;
+  lodash.isUndefined = isUndefined;
+  lodash.lastIndexOf = lastIndexOf;
+  lodash.mixin = mixin;
+  lodash.noConflict = noConflict;
+  lodash.random = random;
+  lodash.reduce = reduce;
+  lodash.reduceRight = reduceRight;
+  lodash.result = result;
+  lodash.size = size;
+  lodash.some = some;
+  lodash.sortedIndex = sortedIndex;
+  lodash.template = template;
+  lodash.unescape = unescape;
+  lodash.uniqueId = uniqueId;
+
+  // add aliases
+  lodash.all = every;
+  lodash.any = some;
+  lodash.detect = find;
+  lodash.findWhere = findWhere;
+  lodash.foldl = reduce;
+  lodash.foldr = reduceRight;
+  lodash.include = contains;
+  lodash.inject = reduce;
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions capable of returning wrapped and unwrapped values when chaining
+  lodash.first = first;
+  lodash.last = last;
+  lodash.sample = sample;
+
+  // add aliases
+  lodash.take = first;
+  lodash.head = first;
+
+  /*--------------------------------------------------------------------------*/
+
+  // add functions to `lodash.prototype`
+  mixin(lodash);
+
+  /**
+   * The semantic version number.
+   *
+   * @static
+   * @memberOf _
+   * @type string
+   */
+  lodash.VERSION = '2.4.1';
+
+  // add "Chaining" functions to the wrapper
+  lodash.prototype.chain = wrapperChain;
+  lodash.prototype.value = wrapperValueOf;
+
+    // add `Array` mutator functions to the wrapper
+    forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        var value = this.__wrapped__;
+        func.apply(value, arguments);
+
+        // avoid array-like object bugs with `Array#shift` and `Array#splice`
+        // in Firefox < 10 and IE < 9
+        if (!support.spliceObjects && value.length === 0) {
+          delete value[0];
+        }
+        return this;
+      };
+    });
+
+    // add `Array` accessor functions to the wrapper
+    forEach(['concat', 'join', 'slice'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        var value = this.__wrapped__,
+            result = func.apply(value, arguments);
+
+        if (this.__chain__) {
+          result = new lodashWrapper(result);
+          result.__chain__ = true;
+        }
+        return result;
+      };
+    });
+
+  /*--------------------------------------------------------------------------*/
+
+  // some AMD build optimizers like r.js check for condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash is loaded with a RequireJS shim config.
+    // See http://requirejs.org/docs/api.html#config-shim
+    root._ = lodash;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return lodash;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports && freeModule) {
+    // in Node.js or RingoJS
+    if (moduleExports) {
+      (freeModule.exports = lodash)._ = lodash;
+    }
+    // in Narwhal or Rhino -require
+    else {
+      freeExports._ = lodash;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    root._ = lodash;
+  }
+}.call(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.underscore.min.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.underscore.min.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/dist/lodash.underscore.min.js	(revision 533)
@@ -0,0 +1,39 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
+ * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js`
+ */
+;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++t<e;)if(n[t]===r)return t;return-1}function r(n,r){for(var t=n.m,e=r.m,u=-1,o=t.length;++u<o;){var i=t[u],f=e[u];if(i!==f){if(i>f||typeof i=="undefined")return 1;if(i<f||typeof f=="undefined")return-1}}return n.n-r.n}function t(n){return"\\"+yr[n]}function e(n,r,t){r||(r=0),typeof t=="undefined"&&(t=n?n.length:0);var e=-1;t=t-r||0;for(var u=Array(0>t?0:t);++e<t;)u[e]=n[r+e];return u}function u(n){return n instanceof u?n:new o(n)}function o(n,r){this.__chain__=!!r,this.__wrapped__=n
+}function i(n){function r(){if(u){var n=e(u);Rr.apply(n,arguments)}if(this instanceof r){var i=f(t.prototype),n=t.apply(i,n||arguments);return O(n)?n:i}return t.apply(o,n||arguments)}var t=n[0],u=n[2],o=n[4];return r}function f(n){return O(n)?Br(n):{}}function a(n,r,t){if(typeof n!="function")return Y;if(typeof r=="undefined"||!("prototype"in n))return n;switch(t){case 1:return function(t){return n.call(r,t)};case 2:return function(t,e){return n.call(r,t,e)};case 3:return function(t,e,u){return n.call(r,t,e,u)
+};case 4:return function(t,e,u,o){return n.call(r,t,e,u,o)}}return L(n,r)}function l(n){function r(){var n=p?a:this;if(o){var y=e(o);Rr.apply(y,arguments)}return(i||g)&&(y||(y=e(arguments)),i&&Rr.apply(y,i),g&&y.length<c)?(u|=16,l([t,h?u:-4&u,y,null,a,c])):(y||(y=arguments),s&&(t=n[v]),this instanceof r?(n=f(t.prototype),y=t.apply(n,y),O(y)?y:n):t.apply(n,y))}var t=n[0],u=n[1],o=n[2],i=n[3],a=n[4],c=n[5],p=1&u,s=2&u,g=4&u,h=8&u,v=t;return r}function c(n,r){for(var t=-1,e=m(),u=n?n.length:0,o=[];++t<u;){var i=n[t];
+0>e(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e<u;){var i=n[e];if(i&&typeof i=="object"&&typeof i.length=="number"&&(Cr(i)||b(i))){r||(i=p(i,r,t));var f=-1,a=i.length,l=o.length;for(o.length+=a;++f<a;)o[l++]=i[f]}else t||o.push(i)}return o}function s(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(n===n&&!(n&&vr[typeof n]||r&&vr[typeof r]))return false;if(null==n||null==r)return n===r;var o=Er.call(n),i=Er.call(r);if(o!=i)return false;switch(o){case lr:case cr:return+n==+r;
+case pr:return n!=+n?r!=+r:0==n?1/n==1/r:n==+r;case gr:case hr:return n==r+""}if(i=o==ar,!i){var f=n instanceof u,a=r instanceof u;if(f||a)return s(f?n.__wrapped__:n,a?r.__wrapped__:r,t,e);if(o!=sr)return false;if(o=n.constructor,f=r.constructor,o!=f&&!(A(o)&&o instanceof o&&A(f)&&f instanceof f)&&"constructor"in n&&"constructor"in r)return false}for(t||(t=[]),e||(e=[]),o=t.length;o--;)if(t[o]==n)return e[o]==r;var l=true,c=0;if(t.push(n),e.push(r),i){if(c=r.length,l=c==n.length)for(;c--&&(l=s(n[c],r[c],t,e)););}else Kr(r,function(r,u,o){return Nr.call(o,u)?(c++,!(l=Nr.call(n,u)&&s(n[u],r,t,e))&&er):void 0
+}),l&&Kr(n,function(n,r,t){return Nr.call(t,r)?!(l=-1<--c)&&er:void 0});return t.pop(),e.pop(),l}function g(n,r,t){for(var e=-1,u=m(),o=n?n.length:0,i=[],f=t?[]:i;++e<o;){var a=n[e],l=t?t(a,e,n):a;(r?!e||f[f.length-1]!==l:0>u(f,l))&&(t&&f.push(l),i.push(a))}return i}function h(n){return function(r,t,e){var u={};t=X(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++e<o;){var i=r[e];n(u,i,t(i,e,r),r)}else Lr(r,function(r,e,o){n(u,r,t(r,e,o),o)});return u}}function v(n,r,t,e,u,o){var f=16&r,a=32&r;
+if(!(2&r||A(n)))throw new TypeError;return f&&!t.length&&(r&=-17,t=false),a&&!e.length&&(r&=-33,e=false),(1==r||17===r?i:l)([n,r,t,e,u,o])}function y(n){return Vr[n]}function m(){var r=(r=u.indexOf)===G?n:r;return r}function _(n){return typeof n=="function"&&Ar.test(n)}function d(n){return Gr[n]}function b(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Er.call(n)==fr||false}function w(n){if(!n)return n;for(var r=1,t=arguments.length;r<t;r++){var e=arguments[r];if(e)for(var u in e)n[u]=e[u]}return n
+}function j(n){if(!n)return n;for(var r=1,t=arguments.length;r<t;r++){var e=arguments[r];if(e)for(var u in e)"undefined"==typeof n[u]&&(n[u]=e[u])}return n}function x(n){var r=[];return Kr(n,function(n,t){A(n)&&r.push(t)}),r.sort()}function T(n){for(var r=-1,t=Ur(n),e=t.length,u={};++r<e;){var o=t[r];u[n[o]]=o}return u}function E(n){if(!n)return true;if(Cr(n)||N(n))return!n.length;for(var r in n)if(Nr.call(n,r))return false;return true}function A(n){return typeof n=="function"}function O(n){return!(!n||!vr[typeof n])
+}function S(n){return typeof n=="number"||n&&typeof n=="object"&&Er.call(n)==pr||false}function N(n){return typeof n=="string"||n&&typeof n=="object"&&Er.call(n)==hr||false}function R(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];return u}function k(n,r){var t=m(),e=n?n.length:0,u=false;return e&&typeof e=="number"?u=-1<t(n,r):Lr(n,function(n){return(u=n===r)&&er}),u}function B(n,r,t){var e=true;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u&&(e=!!r(n[t],t,n)););else Lr(n,function(n,t,u){return!(e=!!r(n,t,u))&&er
+});return e}function F(n,r,t){var e=[];r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u;){var o=n[t];r(o,t,n)&&e.push(o)}else Lr(n,function(n,t,u){r(n,t,u)&&e.push(n)});return e}function q(n,r,t){r=X(r,t,3),t=-1;var e=n?n.length:0;if(typeof e!="number"){var u;return Lr(n,function(n,t,e){return r(n,t,e)?(u=n,er):void 0}),u}for(;++t<e;){var o=n[t];if(r(o,t,n))return o}}function D(n,r,t){var e=-1,u=n?n.length:0;if(r=r&&typeof t=="undefined"?r:a(r,t,3),typeof u=="number")for(;++e<u&&r(n[e],e,n)!==er;);else Lr(n,r)
+}function I(n,r){var t=n?n.length:0;if(typeof t=="number")for(;t--&&false!==r(n[t],t,n););else{var e=Ur(n),t=e.length;Lr(n,function(n,u,o){return u=e?e[--t]:--t,false===r(o[u],u,o)&&er})}}function M(n,r,t){var e=-1,u=n?n.length:0;if(r=X(r,t,3),typeof u=="number")for(var o=Array(u);++e<u;)o[e]=r(n[e],e,n);else o=[],Lr(n,function(n,t,u){o[++e]=r(n,t,u)});return o}function $(n,r,t){var e=-1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++o<i;)t=n[o],t>u&&(u=t);
+else r=X(r,t,3),D(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function W(n,r,t,e){if(!n)return t;var u=3>arguments.length;r=X(r,e,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(t=n[++o]);++o<i;)t=r(t,n[o],o,n);else Lr(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)});return t}function z(n,r,t,e){var u=3>arguments.length;return r=X(r,e,4),I(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return D(n,function(n){var t;t=++r,t=0+Sr(Wr()*(t-0+1)),e[r]=e[t],e[t]=n
+}),e}function P(n,r,t){var e;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u&&!(e=r(n[t],t,n)););else Lr(n,function(n,t,u){return(e=r(n,t,u))&&er});return!!e}function U(n,r,t){return t&&E(r)?rr:(t?q:F)(n,r)}function V(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=-1;for(r=X(r,t,3);++i<o&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[0]:rr;return e(n,0,$r(Mr(0,u),o))}function G(r,t,e){if(typeof e=="number"){var u=r?r.length:0;e=0>e?Mr(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1;
+return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o<i&&r(n[o],o,n);)u++}else u=null==r||t?1:Mr(0,r);return e(n,u)}function J(n,r,t,e){var u=0,o=n?n.length:u;for(t=t?X(t,e,1):Y,r=t(r);u<o;)e=u+o>>>1,t(n[e])<r?u=e+1:o=e;return u}function K(n,r,t,e){return typeof r!="boolean"&&null!=r&&(e=t,t=typeof r!="function"&&e&&e[r]===n?null:r,r=false),null!=t&&(t=X(t,e,3)),g(n,r,t)}function L(n,r){return 2<arguments.length?v(n,17,e(arguments,2),null,r):v(n,1,null,null,r)
+}function Q(n,r,t){var e,u,o,i,f,a,l,c=0,p=false,s=true;if(!A(n))throw new TypeError;if(r=Mr(0,r)||0,true===t)var g=true,s=false;else O(t)&&(g=t.leading,p="maxWait"in t&&(Mr(r,t.maxWait)||0),s="trailing"in t?t.trailing:s);var h=function(){var t=r-(nt()-i);0<t?a=setTimeout(h,t):(u&&clearTimeout(u),t=l,u=a=l=rr,t&&(c=nt(),o=n.apply(f,e),a||u||(e=f=null)))},v=function(){a&&clearTimeout(a),u=a=l=rr,(s||p!==r)&&(c=nt(),o=n.apply(f,e),a||u||(e=f=null))};return function(){if(e=arguments,i=nt(),f=this,l=s&&(a||!g),false===p)var t=g&&!a;
+else{u||g||(c=i);var y=p-(i-c),m=0>=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;if(null==n||"function"==e)return a(n,r,t);if("object"!=e)return nr(n);var u=Ur(n);return function(r){for(var t=u.length,e=false;t--&&(e=r[u[t]]===n[u[t]]););return e}}function Y(n){return n}function Z(n){D(x(n),function(r){var t=u[r]=n[r];u.prototype[r]=function(){var n=[this.__wrapped__];
+return Rr.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function nr(n){return function(r){return r[n]}}var rr,tr=0,er={},ur=+new Date+"",or=/($^)/,ir=/['\n\r\t\u2028\u2029\\]/g,fr="[object Arguments]",ar="[object Array]",lr="[object Boolean]",cr="[object Date]",pr="[object Number]",sr="[object Object]",gr="[object RegExp]",hr="[object String]",vr={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},yr={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},mr=vr[typeof window]&&window||this,_r=vr[typeof exports]&&exports&&!exports.nodeType&&exports,dr=vr[typeof module]&&module&&!module.nodeType&&module,br=dr&&dr.exports===_r&&_r,wr=vr[typeof global]&&global;
+!wr||wr.global!==wr&&wr.window!==wr||(mr=wr);var jr=[],xr=Object.prototype,Tr=mr._,Er=xr.toString,Ar=RegExp("^"+(Er+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),Or=Math.ceil,Sr=Math.floor,Nr=xr.hasOwnProperty,Rr=jr.push,kr=xr.propertyIsEnumerable,Br=_(Br=Object.create)&&Br,Fr=_(Fr=Array.isArray)&&Fr,qr=mr.isFinite,Dr=mr.isNaN,Ir=_(Ir=Object.keys)&&Ir,Mr=Math.max,$r=Math.min,Wr=Math.random;o.prototype=u.prototype;var zr={};!function(){var n={0:1,length:1};zr.spliceObjects=(jr.splice.call(n,0,1),!n[0])
+}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Br||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||mr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n,"callee")&&!kr.call(n,"callee")||false});var Cr=Fr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Er.call(n)==ar||false},Pr=function(n){var r,t=[];
+if(!n||!vr[typeof n])return t;for(r in n)Nr.call(n,r)&&t.push(r);return t},Ur=Ir?function(n){return O(n)?Ir(n):[]}:Pr,Vr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"},Gr=T(Vr),Hr=RegExp("("+Ur(Gr).join("|")+")","g"),Jr=RegExp("["+Ur(Vr).join("")+"]","g"),Kr=function(n,r){var t;if(!n||!vr[typeof n])return n;for(t in n)if(r(n[t],t,n)===er)break;return n},Lr=function(n,r){var t;if(!n||!vr[typeof n])return n;for(t in n)if(Nr.call(n,t)&&r(n[t],t,n)===er)break;return n};A(/x/)&&(A=function(n){return typeof n=="function"&&"[object Function]"==Er.call(n)
+});var Qr=h(function(n,r,t){Nr.call(n,t)?n[t]++:n[t]=1}),Xr=h(function(n,r,t){(Nr.call(n,t)?n[t]:n[t]=[]).push(r)}),Yr=h(function(n,r,t){n[t]=r}),Zr=M,nt=_(nt=Date.now)&&nt||function(){return(new Date).getTime()};u.after=function(n,r){if(!A(r))throw new TypeError;return function(){return 1>--n?r.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var r=1<arguments.length?p(arguments,true,false,1):x(n),t=-1,e=r.length;++t<e;){var u=r[t];n[u]=v(n[u],1,null,null,n)}return n},u.chain=function(n){return n=new o(n),n.__chain__=true,n
+},u.compact=function(n){for(var r=-1,t=n?n.length:0,e=[];++r<t;){var u=n[r];u&&e.push(u)}return e},u.compose=function(){for(var n=arguments,r=n.length;r--;)if(!A(n[r]))throw new TypeError;return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}},u.countBy=Qr,u.debounce=Q,u.defaults=j,u.defer=function(n){if(!A(n))throw new TypeError;var r=e(arguments,1);return setTimeout(function(){n.apply(rr,r)},1)},u.delay=function(n,r){if(!A(n))throw new TypeError;var t=e(arguments,2);
+return setTimeout(function(){n.apply(rr,t)},r)},u.difference=function(n){return c(n,p(arguments,true,true,1))},u.filter=F,u.flatten=function(n,r){return p(n,r)},u.forEach=D,u.functions=x,u.groupBy=Xr,u.indexBy=Yr,u.initial=function(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else u=null==r||t?1:r||u;return e(n,0,$r(Mr(0,o-u),o))},u.intersection=function(){for(var n=[],r=-1,t=arguments.length;++r<t;){var e=arguments[r];(Cr(e)||b(e))&&n.push(e)
+}var u=n[0],o=-1,i=m(),f=u?u.length:0,a=[];n:for(;++o<f;)if(e=u[o],0>i(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},u.invert=T,u.invoke=function(n,r){var t=e(arguments,2),u=-1,o=typeof r=="function",i=n?n.length:0,f=Array(typeof i=="number"?i:0);return D(n,function(n){f[++u]=(o?r:n[r]).apply(n,t)}),f},u.keys=Ur,u.map=M,u.max=$,u.memoize=function(n,r){var t={};return function(){var e=r?r.apply(this,arguments):ur+arguments[0];return Nr.call(t,e)?t[e]:t[e]=n.apply(this,arguments)
+}},u.min=function(n,r,t){var e=1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++o<i;)t=n[o],t<u&&(u=t);else r=X(r,t,3),D(n,function(n,t,o){t=r(n,t,o),t<e&&(e=t,u=n)});return u},u.omit=function(n){var r=[];Kr(n,function(n,t){r.push(t)});for(var r=c(r,p(arguments,true,false,1)),t=-1,e=r.length,u={};++t<e;){var o=r[t];u[o]=n[o]}return u},u.once=function(n){var r,t;if(!A(n))throw new TypeError;return function(){return r?t:(r=true,t=n.apply(this,arguments),n=null,t)
+}},u.pairs=function(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++r<e;){var o=t[r];u[r]=[o,n[o]]}return u},u.partial=function(n){return v(n,16,e(arguments,1))},u.pick=function(n){for(var r=-1,t=p(arguments,true,false,1),e=t.length,u={};++r<e;){var o=t[r];o in n&&(u[o]=n[o])}return u},u.pluck=Zr,u.range=function(n,r,t){n=+n||0,t=+t||1,null==r&&(r=n,n=0);var e=-1;r=Mr(0,Or((r-n)/t));for(var u=Array(r);++e<r;)u[e]=n,n+=t;return u},u.reject=function(n,r,t){return r=X(r,t,3),F(n,function(n,t,e){return!r(n,t,e)
+})},u.rest=H,u.shuffle=C,u.sortBy=function(n,t,e){var u=-1,o=n?n.length:0,i=Array(typeof o=="number"?o:0);for(t=X(t,e,3),D(n,function(n,r,e){i[++u]={m:[t(n,r,e)],n:u,o:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].o;return i},u.tap=function(n,r){return r(n),n},u.throttle=function(n,r,t){var e=true,u=true;if(!A(n))throw new TypeError;return false===t?e=false:O(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),t={},t.leading=e,t.maxWait=r,t.trailing=u,Q(n,r,t)},u.times=function(n,r,t){n=-1<(n=+n)?n:0;
+var e=-1,u=Array(n);for(r=a(r,t,1);++e<n;)u[e]=r(e);return u},u.toArray=function(n){return Cr(n)?e(n):n&&typeof n.length=="number"?M(n):R(n)},u.union=function(){return g(p(arguments,true,true))},u.uniq=K,u.values=R,u.where=U,u.without=function(n){return c(n,e(arguments,1))},u.wrap=function(n,r){return v(r,16,[n])},u.zip=function(){for(var n=-1,r=$(Zr(arguments,"length")),t=Array(0>r?0:r);++n<r;)t[n]=Zr(arguments,n);return t},u.collect=M,u.drop=H,u.each=D,u.extend=w,u.methods=x,u.object=function(n,r){var t=-1,e=n?n.length:0,u={};
+for(r||!e||Cr(n[0])||(r=[]);++t<e;){var o=n[t];r?u[o]=r[t]:o&&(u[o[0]]=o[1])}return u},u.select=F,u.tail=H,u.unique=K,u.clone=function(n){return O(n)?Cr(n)?e(n):w({},n):n},u.contains=k,u.escape=function(n){return null==n?"":(n+"").replace(Jr,y)},u.every=B,u.find=q,u.has=function(n,r){return n?Nr.call(n,r):false},u.identity=Y,u.indexOf=G,u.isArguments=b,u.isArray=Cr,u.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&Er.call(n)==lr||false},u.isDate=function(n){return n&&typeof n=="object"&&Er.call(n)==cr||false
+},u.isElement=function(n){return n&&1===n.nodeType||false},u.isEmpty=E,u.isEqual=function(n,r){return s(n,r)},u.isFinite=function(n){return qr(n)&&!Dr(parseFloat(n))},u.isFunction=A,u.isNaN=function(n){return S(n)&&n!=+n},u.isNull=function(n){return null===n},u.isNumber=S,u.isObject=O,u.isRegExp=function(n){return n&&vr[typeof n]&&Er.call(n)==gr||false},u.isString=N,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?Mr(0,e+t):$r(t,e-1))+1);e--;)if(n[e]===r)return e;
+return-1},u.mixin=Z,u.noConflict=function(){return mr._=Tr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Sr(Wr()*(r-n+1))},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return A(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Ur(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||or).source+"|"+(e.interpolate||or).source+"|"+(e.evaluate||or).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(ir,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r
+}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+"").replace(Hr,d)},u.uniqueId=function(n){var r=++tr+"";return n?n+r:r},u.all=B,u.any=P,u.detect=q,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=k,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0;
+if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:rr;return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=R(n)),null==r||t?n?n[0+Sr(Wr()*(n.length-1-0+1))]:rr:(n=C(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(u),u.VERSION="2.4.1",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},D("pop push reverse shift sort splice unshift".split(" "),function(n){var r=jr[n];
+u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),zr.spliceObjects||0!==n.length||delete n[0],this}}),D(["concat","join","slice"],function(n){var r=jr[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(mr._=u, define(function(){return u})):_r&&dr?br?(dr.exports=u)._=u:_r._=u:mr._=u}).call(this);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/lodash.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/lodash.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/lodash.js	(revision 533)
@@ -0,0 +1,7179 @@
+/**
+ * @license
+ * Lo-Dash 2.4.1 <http://lodash.com/>
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function() {
+
+  /** Used as a safe reference for `undefined` in pre ES5 environments */
+  var undefined;
+
+  /** Used to pool arrays and objects used internally */
+  var arrayPool = [],
+      objectPool = [];
+
+  /** Used to generate unique IDs */
+  var idCounter = 0;
+
+  /** Used internally to indicate various things */
+  var indicatorObject = {};
+
+  /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
+  var keyPrefix = +new Date + '';
+
+  /** Used as the size when optimizations are enabled for large arrays */
+  var largeArraySize = 75;
+
+  /** Used as the max size of the `arrayPool` and `objectPool` */
+  var maxPoolSize = 40;
+
+  /** Used to detect and test whitespace */
+  var whitespace = (
+    // whitespace
+    ' \t\x0B\f\xA0\ufeff' +
+
+    // line terminators
+    '\n\r\u2028\u2029' +
+
+    // unicode category "Zs" space separators
+    '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
+  );
+
+  /** Used to match empty string literals in compiled template source */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /**
+   * Used to match ES6 template delimiters
+   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
+   */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match regexp flags from their coerced string values */
+  var reFlags = /\w*$/;
+
+  /** Used to detected named functions */
+  var reFuncName = /^\s*function[ \n\r\t]+\w/;
+
+  /** Used to match "interpolate" template delimiters */
+  var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to match leading whitespace and zeros to be removed */
+  var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
+
+  /** Used to ensure capturing order of template delimiters */
+  var reNoMatch = /($^)/;
+
+  /** Used to detect functions containing a `this` reference */
+  var reThis = /\bthis\b/;
+
+  /** Used to match unescaped characters in compiled string literals */
+  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+  /** Used to assign default `context` object properties */
+  var contextProps = [
+    'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object',
+    'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
+    'parseInt', 'setTimeout'
+  ];
+
+  /** Used to fix the JScript [[DontEnum]] bug */
+  var shadowedProps = [
+    'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+    'toLocaleString', 'toString', 'valueOf'
+  ];
+
+  /** Used to make template sourceURLs easier to identify */
+  var templateCounter = 0;
+
+  /** `Object#toString` result shortcuts */
+  var argsClass = '[object Arguments]',
+      arrayClass = '[object Array]',
+      boolClass = '[object Boolean]',
+      dateClass = '[object Date]',
+      errorClass = '[object Error]',
+      funcClass = '[object Function]',
+      numberClass = '[object Number]',
+      objectClass = '[object Object]',
+      regexpClass = '[object RegExp]',
+      stringClass = '[object String]';
+
+  /** Used to identify object classifications that `_.clone` supports */
+  var cloneableClasses = {};
+  cloneableClasses[funcClass] = false;
+  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
+  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
+  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
+
+  /** Used as an internal `_.debounce` options object */
+  var debounceOptions = {
+    'leading': false,
+    'maxWait': 0,
+    'trailing': false
+  };
+
+  /** Used as the property descriptor for `__bindData__` */
+  var descriptor = {
+    'configurable': false,
+    'enumerable': false,
+    'value': null,
+    'writable': false
+  };
+
+  /** Used as the data object for `iteratorTemplate` */
+  var iteratorData = {
+    'args': '',
+    'array': null,
+    'bottom': '',
+    'firstArg': '',
+    'init': '',
+    'keys': null,
+    'loop': '',
+    'shadowedProps': null,
+    'support': null,
+    'top': '',
+    'useHas': false
+  };
+
+  /** Used to determine if values are of the language type Object */
+  var objectTypes = {
+    'boolean': false,
+    'function': true,
+    'object': true,
+    'number': false,
+    'string': false,
+    'undefined': false
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\t': 't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /** Used as a reference to the global object */
+  var root = (objectTypes[typeof window] && window) || this;
+
+  /** Detect free variable `exports` */
+  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+  /** Detect free variable `module` */
+  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+  /** Detect the popular CommonJS extension `module.exports` */
+  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+  /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
+  var freeGlobal = objectTypes[typeof global] && global;
+  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
+    root = freeGlobal;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The base implementation of `_.indexOf` without support for binary searches
+   * or `fromIndex` constraints.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {number} [fromIndex=0] The index to search from.
+   * @returns {number} Returns the index of the matched value or `-1`.
+   */
+  function baseIndexOf(array, value, fromIndex) {
+    var index = (fromIndex || 0) - 1,
+        length = array ? array.length : 0;
+
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * An implementation of `_.contains` for cache objects that mimics the return
+   * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
+   *
+   * @private
+   * @param {Object} cache The cache object to inspect.
+   * @param {*} value The value to search for.
+   * @returns {number} Returns `0` if `value` is found, else `-1`.
+   */
+  function cacheIndexOf(cache, value) {
+    var type = typeof value;
+    cache = cache.cache;
+
+    if (type == 'boolean' || value == null) {
+      return cache[value] ? 0 : -1;
+    }
+    if (type != 'number' && type != 'string') {
+      type = 'object';
+    }
+    var key = type == 'number' ? value : keyPrefix + value;
+    cache = (cache = cache[type]) && cache[key];
+
+    return type == 'object'
+      ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
+      : (cache ? 0 : -1);
+  }
+
+  /**
+   * Adds a given value to the corresponding cache object.
+   *
+   * @private
+   * @param {*} value The value to add to the cache.
+   */
+  function cachePush(value) {
+    var cache = this.cache,
+        type = typeof value;
+
+    if (type == 'boolean' || value == null) {
+      cache[value] = true;
+    } else {
+      if (type != 'number' && type != 'string') {
+        type = 'object';
+      }
+      var key = type == 'number' ? value : keyPrefix + value,
+          typeCache = cache[type] || (cache[type] = {});
+
+      if (type == 'object') {
+        (typeCache[key] || (typeCache[key] = [])).push(value);
+      } else {
+        typeCache[key] = true;
+      }
+    }
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default callback when a given
+   * collection is a string value.
+   *
+   * @private
+   * @param {string} value The character to inspect.
+   * @returns {number} Returns the code unit of given character.
+   */
+  function charAtCallback(value) {
+    return value.charCodeAt(0);
+  }
+
+  /**
+   * Used by `sortBy` to compare transformed `collection` elements, stable sorting
+   * them in ascending order.
+   *
+   * @private
+   * @param {Object} a The object to compare to `b`.
+   * @param {Object} b The object to compare to `a`.
+   * @returns {number} Returns the sort order indicator of `1` or `-1`.
+   */
+  function compareAscending(a, b) {
+    var ac = a.criteria,
+        bc = b.criteria,
+        index = -1,
+        length = ac.length;
+
+    while (++index < length) {
+      var value = ac[index],
+          other = bc[index];
+
+      if (value !== other) {
+        if (value > other || typeof value == 'undefined') {
+          return 1;
+        }
+        if (value < other || typeof other == 'undefined') {
+          return -1;
+        }
+      }
+    }
+    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+    // that causes it, under certain circumstances, to return the same value for
+    // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
+    //
+    // This also ensures a stable sort in V8 and other engines.
+    // See http://code.google.com/p/v8/issues/detail?id=90
+    return a.index - b.index;
+  }
+
+  /**
+   * Creates a cache object to optimize linear searches of large arrays.
+   *
+   * @private
+   * @param {Array} [array=[]] The array to search.
+   * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
+   */
+  function createCache(array) {
+    var index = -1,
+        length = array.length,
+        first = array[0],
+        mid = array[(length / 2) | 0],
+        last = array[length - 1];
+
+    if (first && typeof first == 'object' &&
+        mid && typeof mid == 'object' && last && typeof last == 'object') {
+      return false;
+    }
+    var cache = getObject();
+    cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
+
+    var result = getObject();
+    result.array = array;
+    result.cache = cache;
+    result.push = cachePush;
+
+    while (++index < length) {
+      result.push(array[index]);
+    }
+    return result;
+  }
+
+  /**
+   * Used by `template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {string} match The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeStringChar(match) {
+    return '\\' + stringEscapes[match];
+  }
+
+  /**
+   * Gets an array from the array pool or creates a new one if the pool is empty.
+   *
+   * @private
+   * @returns {Array} The array from the pool.
+   */
+  function getArray() {
+    return arrayPool.pop() || [];
+  }
+
+  /**
+   * Gets an object from the object pool or creates a new one if the pool is empty.
+   *
+   * @private
+   * @returns {Object} The object from the pool.
+   */
+  function getObject() {
+    return objectPool.pop() || {
+      'array': null,
+      'cache': null,
+      'criteria': null,
+      'false': false,
+      'index': 0,
+      'null': false,
+      'number': null,
+      'object': null,
+      'push': null,
+      'string': null,
+      'true': false,
+      'undefined': false,
+      'value': null
+    };
+  }
+
+  /**
+   * Checks if `value` is a DOM node in IE < 9.
+   *
+   * @private
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`.
+   */
+  function isNode(value) {
+    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+    // methods that are `typeof` "string" and still can coerce nodes to strings
+    return typeof value.toString != 'function' && typeof (value + '') == 'string';
+  }
+
+  /**
+   * Releases the given array back to the array pool.
+   *
+   * @private
+   * @param {Array} [array] The array to release.
+   */
+  function releaseArray(array) {
+    array.length = 0;
+    if (arrayPool.length < maxPoolSize) {
+      arrayPool.push(array);
+    }
+  }
+
+  /**
+   * Releases the given object back to the object pool.
+   *
+   * @private
+   * @param {Object} [object] The object to release.
+   */
+  function releaseObject(object) {
+    var cache = object.cache;
+    if (cache) {
+      releaseObject(cache);
+    }
+    object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
+    if (objectPool.length < maxPoolSize) {
+      objectPool.push(object);
+    }
+  }
+
+  /**
+   * Slices the `collection` from the `start` index up to, but not including,
+   * the `end` index.
+   *
+   * Note: This function is used instead of `Array#slice` to support node lists
+   * in IE < 9 and to ensure dense arrays are returned.
+   *
+   * @private
+   * @param {Array|Object|string} collection The collection to slice.
+   * @param {number} start The start index.
+   * @param {number} end The end index.
+   * @returns {Array} Returns the new array.
+   */
+  function slice(array, start, end) {
+    start || (start = 0);
+    if (typeof end == 'undefined') {
+      end = array ? array.length : 0;
+    }
+    var index = -1,
+        length = end - start || 0,
+        result = Array(length < 0 ? 0 : length);
+
+    while (++index < length) {
+      result[index] = array[start + index];
+    }
+    return result;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Create a new `lodash` function using the given context object.
+   *
+   * @static
+   * @memberOf _
+   * @category Utilities
+   * @param {Object} [context=root] The context object.
+   * @returns {Function} Returns the `lodash` function.
+   */
+  function runInContext(context) {
+    // Avoid issues with some ES3 environments that attempt to use values, named
+    // after built-in constructors like `Object`, for the creation of literals.
+    // ES5 clears this up by stating that literals must use built-in constructors.
+    // See http://es5.github.io/#x11.1.5.
+    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+
+    /** Native constructor references */
+    var Array = context.Array,
+        Boolean = context.Boolean,
+        Date = context.Date,
+        Error = context.Error,
+        Function = context.Function,
+        Math = context.Math,
+        Number = context.Number,
+        Object = context.Object,
+        RegExp = context.RegExp,
+        String = context.String,
+        TypeError = context.TypeError;
+
+    /**
+     * Used for `Array` method references.
+     *
+     * Normally `Array.prototype` would suffice, however, using an array literal
+     * avoids issues in Narwhal.
+     */
+    var arrayRef = [];
+
+    /** Used for native method references */
+    var errorProto = Error.prototype,
+        objectProto = Object.prototype,
+        stringProto = String.prototype;
+
+    /** Used to restore the original `_` reference in `noConflict` */
+    var oldDash = context._;
+
+    /** Used to resolve the internal [[Class]] of values */
+    var toString = objectProto.toString;
+
+    /** Used to detect if a method is native */
+    var reNative = RegExp('^' +
+      String(toString)
+        .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+        .replace(/toString| for [^\]]+/g, '.*?') + '$'
+    );
+
+    /** Native method shortcuts */
+    var ceil = Math.ceil,
+        clearTimeout = context.clearTimeout,
+        floor = Math.floor,
+        fnToString = Function.prototype.toString,
+        getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+        hasOwnProperty = objectProto.hasOwnProperty,
+        push = arrayRef.push,
+        propertyIsEnumerable = objectProto.propertyIsEnumerable,
+        setTimeout = context.setTimeout,
+        splice = arrayRef.splice,
+        unshift = arrayRef.unshift;
+
+    /** Used to set meta data on functions */
+    var defineProperty = (function() {
+      // IE 8 only accepts DOM elements
+      try {
+        var o = {},
+            func = isNative(func = Object.defineProperty) && func,
+            result = func(o, o, o) && func;
+      } catch(e) { }
+      return result;
+    }());
+
+    /* Native method shortcuts for methods with the same name as other `lodash` methods */
+    var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
+        nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
+        nativeIsFinite = context.isFinite,
+        nativeIsNaN = context.isNaN,
+        nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
+        nativeMax = Math.max,
+        nativeMin = Math.min,
+        nativeParseInt = context.parseInt,
+        nativeRandom = Math.random;
+
+    /** Used to lookup a built-in constructor by [[Class]] */
+    var ctorByClass = {};
+    ctorByClass[arrayClass] = Array;
+    ctorByClass[boolClass] = Boolean;
+    ctorByClass[dateClass] = Date;
+    ctorByClass[funcClass] = Function;
+    ctorByClass[objectClass] = Object;
+    ctorByClass[numberClass] = Number;
+    ctorByClass[regexpClass] = RegExp;
+    ctorByClass[stringClass] = String;
+
+    /** Used to avoid iterating non-enumerable properties in IE < 9 */
+    var nonEnumProps = {};
+    nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
+    nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true };
+    nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true };
+    nonEnumProps[objectClass] = { 'constructor': true };
+
+    (function() {
+      var length = shadowedProps.length;
+      while (length--) {
+        var key = shadowedProps[length];
+        for (var className in nonEnumProps) {
+          if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) {
+            nonEnumProps[className][key] = false;
+          }
+        }
+      }
+    }());
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object which wraps the given value to enable intuitive
+     * method chaining.
+     *
+     * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+     * and `unshift`
+     *
+     * Chaining is supported in custom builds as long as the `value` method is
+     * implicitly or explicitly included in the build.
+     *
+     * The chainable wrapper functions are:
+     * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
+     * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
+     * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
+     * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
+     * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
+     * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
+     * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
+     * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
+     * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
+     * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
+     * and `zip`
+     *
+     * The non-chainable wrapper functions are:
+     * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
+     * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
+     * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
+     * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
+     * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
+     * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
+     * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
+     * `template`, `unescape`, `uniqueId`, and `value`
+     *
+     * The wrapper functions `first` and `last` return wrapped values when `n` is
+     * provided, otherwise they return unwrapped values.
+     *
+     * Explicit chaining can be enabled by using the `_.chain` method.
+     *
+     * @name _
+     * @constructor
+     * @category Chaining
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @returns {Object} Returns a `lodash` instance.
+     * @example
+     *
+     * var wrapped = _([1, 2, 3]);
+     *
+     * // returns an unwrapped value
+     * wrapped.reduce(function(sum, num) {
+     *   return sum + num;
+     * });
+     * // => 6
+     *
+     * // returns a wrapped value
+     * var squares = wrapped.map(function(num) {
+     *   return num * num;
+     * });
+     *
+     * _.isArray(squares);
+     * // => false
+     *
+     * _.isArray(squares.value());
+     * // => true
+     */
+    function lodash(value) {
+      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
+      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
+       ? value
+       : new lodashWrapper(value);
+    }
+
+    /**
+     * A fast path for creating `lodash` wrapper objects.
+     *
+     * @private
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @param {boolean} chainAll A flag to enable chaining for all methods
+     * @returns {Object} Returns a `lodash` instance.
+     */
+    function lodashWrapper(value, chainAll) {
+      this.__chain__ = !!chainAll;
+      this.__wrapped__ = value;
+    }
+    // ensure `new lodashWrapper` is an instance of `lodash`
+    lodashWrapper.prototype = lodash.prototype;
+
+    /**
+     * An object used to flag environments features.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    var support = lodash.support = {};
+
+    (function() {
+      var ctor = function() { this.x = 1; },
+          object = { '0': 1, 'length': 1 },
+          props = [];
+
+      ctor.prototype = { 'valueOf': 1, 'y': 1 };
+      for (var key in new ctor) { props.push(key); }
+      for (key in arguments) { }
+
+      /**
+       * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.argsClass = toString.call(arguments) == argsClass;
+
+      /**
+       * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.argsObject = arguments.constructor == Object && !(arguments instanceof Array);
+
+      /**
+       * Detect if `name` or `message` properties of `Error.prototype` are
+       * enumerable by default. (IE < 9, Safari < 5.1)
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name');
+
+      /**
+       * Detect if `prototype` properties are enumerable by default.
+       *
+       * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+       * (if the prototype or a property on the prototype has been set)
+       * incorrectly sets a function's `prototype` property [[Enumerable]]
+       * value to `true`.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype');
+
+      /**
+       * Detect if functions can be decompiled by `Function#toString`
+       * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
+
+      /**
+       * Detect if `Function#name` is supported (all but IE).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.funcNames = typeof Function.name == 'string';
+
+      /**
+       * Detect if `arguments` object indexes are non-enumerable
+       * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.nonEnumArgs = key != 0;
+
+      /**
+       * Detect if properties shadowing those on `Object.prototype` are non-enumerable.
+       *
+       * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+       * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.nonEnumShadows = !/valueOf/.test(props);
+
+      /**
+       * Detect if own properties are iterated after inherited properties (all but IE < 9).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.ownLast = props[0] != 'x';
+
+      /**
+       * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.
+       *
+       * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+       * and `splice()` functions that fail to remove the last element, `value[0]`,
+       * of array-like objects even though the `length` property is set to `0`.
+       * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+       * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);
+
+      /**
+       * Detect lack of support for accessing string characters by index.
+       *
+       * IE < 8 can't access characters by index and IE 8 can only access
+       * characters by index on string literals.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
+
+      /**
+       * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9)
+       * and that the JS engine errors when attempting to coerce an object to
+       * a string without a `toString` function.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      try {
+        support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
+      } catch(e) {
+        support.nodeClass = true;
+      }
+    }(1));
+
+    /**
+     * By default, the template delimiters used by Lo-Dash are similar to those in
+     * embedded Ruby (ERB). Change the following template settings to use alternative
+     * delimiters.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    lodash.templateSettings = {
+
+      /**
+       * Used to detect `data` property values to be HTML-escaped.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'escape': /<%-([\s\S]+?)%>/g,
+
+      /**
+       * Used to detect code to be evaluated.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'evaluate': /<%([\s\S]+?)%>/g,
+
+      /**
+       * Used to detect `data` property values to inject.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'interpolate': reInterpolate,
+
+      /**
+       * Used to reference the data object in the template text.
+       *
+       * @memberOf _.templateSettings
+       * @type string
+       */
+      'variable': '',
+
+      /**
+       * Used to import variables into the compiled template.
+       *
+       * @memberOf _.templateSettings
+       * @type Object
+       */
+      'imports': {
+
+        /**
+         * A reference to the `lodash` function.
+         *
+         * @memberOf _.templateSettings.imports
+         * @type Function
+         */
+        '_': lodash
+      }
+    };
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The template used to create iterator functions.
+     *
+     * @private
+     * @param {Object} data The data object used to populate the text.
+     * @returns {string} Returns the interpolated text.
+     */
+    var iteratorTemplate = template(
+      // the `iterable` may be reassigned by the `top` snippet
+      'var index, iterable = <%= firstArg %>, ' +
+      // assign the `result` variable an initial value
+      'result = <%= init %>;\n' +
+      // exit early if the first argument is falsey
+      'if (!iterable) return result;\n' +
+      // add code before the iteration branches
+      '<%= top %>;' +
+
+      // array-like iteration:
+      '<% if (array) { %>\n' +
+      'var length = iterable.length; index = -1;\n' +
+      'if (<%= array %>) {' +
+
+      // add support for accessing string characters by index if needed
+      '  <% if (support.unindexedChars) { %>\n' +
+      '  if (isString(iterable)) {\n' +
+      "    iterable = iterable.split('')\n" +
+      '  }' +
+      '  <% } %>\n' +
+
+      // iterate over the array-like value
+      '  while (++index < length) {\n' +
+      '    <%= loop %>;\n' +
+      '  }\n' +
+      '}\n' +
+      'else {' +
+
+      // object iteration:
+      // add support for iterating over `arguments` objects if needed
+      '  <% } else if (support.nonEnumArgs) { %>\n' +
+      '  var length = iterable.length; index = -1;\n' +
+      '  if (length && isArguments(iterable)) {\n' +
+      '    while (++index < length) {\n' +
+      "      index += '';\n" +
+      '      <%= loop %>;\n' +
+      '    }\n' +
+      '  } else {' +
+      '  <% } %>' +
+
+      // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari
+      '  <% if (support.enumPrototypes) { %>\n' +
+      "  var skipProto = typeof iterable == 'function';\n" +
+      '  <% } %>' +
+
+      // avoid iterating over `Error.prototype` properties in older IE and Safari
+      '  <% if (support.enumErrorProps) { %>\n' +
+      '  var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n' +
+      '  <% } %>' +
+
+      // define conditions used in the loop
+      '  <%' +
+      '    var conditions = [];' +
+      '    if (support.enumPrototypes) { conditions.push(\'!(skipProto && index == "prototype")\'); }' +
+      '    if (support.enumErrorProps)  { conditions.push(\'!(skipErrorProps && (index == "message" || index == "name"))\'); }' +
+      '  %>' +
+
+      // iterate own properties using `Object.keys`
+      '  <% if (useHas && keys) { %>\n' +
+      '  var ownIndex = -1,\n' +
+      '      ownProps = objectTypes[typeof iterable] && keys(iterable),\n' +
+      '      length = ownProps ? ownProps.length : 0;\n\n' +
+      '  while (++ownIndex < length) {\n' +
+      '    index = ownProps[ownIndex];\n<%' +
+      "    if (conditions.length) { %>    if (<%= conditions.join(' && ') %>) {\n  <% } %>" +
+      '    <%= loop %>;' +
+      '    <% if (conditions.length) { %>\n    }<% } %>\n' +
+      '  }' +
+
+      // else using a for-in loop
+      '  <% } else { %>\n' +
+      '  for (index in iterable) {\n<%' +
+      '    if (useHas) { conditions.push("hasOwnProperty.call(iterable, index)"); }' +
+      "    if (conditions.length) { %>    if (<%= conditions.join(' && ') %>) {\n  <% } %>" +
+      '    <%= loop %>;' +
+      '    <% if (conditions.length) { %>\n    }<% } %>\n' +
+      '  }' +
+
+      // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
+      // existing property and the `constructor` property of a prototype
+      // defaults to non-enumerable, Lo-Dash skips the `constructor`
+      // property when it infers it's iterating over a `prototype` object.
+      '    <% if (support.nonEnumShadows) { %>\n\n' +
+      '  if (iterable !== objectProto) {\n' +
+      "    var ctor = iterable.constructor,\n" +
+      '        isProto = iterable === (ctor && ctor.prototype),\n' +
+      '        className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n' +
+      '        nonEnum = nonEnumProps[className];\n' +
+      '      <% for (k = 0; k < 7; k++) { %>\n' +
+      "    index = '<%= shadowedProps[k] %>';\n" +
+      '    if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))<%' +
+      '        if (!useHas) { %> || (!nonEnum[index] && iterable[index] !== objectProto[index])<% }' +
+      '      %>) {\n' +
+      '      <%= loop %>;\n' +
+      '    }' +
+      '      <% } %>\n' +
+      '  }' +
+      '    <% } %>' +
+      '  <% } %>' +
+      '  <% if (array || support.nonEnumArgs) { %>\n}<% } %>\n' +
+
+      // add code to the bottom of the iteration function
+      '<%= bottom %>;\n' +
+      // finally, return the `result`
+      'return result'
+    );
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The base implementation of `_.bind` that creates the bound function and
+     * sets its meta data.
+     *
+     * @private
+     * @param {Array} bindData The bind data array.
+     * @returns {Function} Returns the new bound function.
+     */
+    function baseBind(bindData) {
+      var func = bindData[0],
+          partialArgs = bindData[2],
+          thisArg = bindData[4];
+
+      function bound() {
+        // `Function#bind` spec
+        // http://es5.github.io/#x15.3.4.5
+        if (partialArgs) {
+          // avoid `arguments` object deoptimizations by using `slice` instead
+          // of `Array.prototype.slice.call` and not assigning `arguments` to a
+          // variable as a ternary expression
+          var args = slice(partialArgs);
+          push.apply(args, arguments);
+        }
+        // mimic the constructor's `return` behavior
+        // http://es5.github.io/#x13.2.2
+        if (this instanceof bound) {
+          // ensure `new bound` is an instance of `func`
+          var thisBinding = baseCreate(func.prototype),
+              result = func.apply(thisBinding, args || arguments);
+          return isObject(result) ? result : thisBinding;
+        }
+        return func.apply(thisArg, args || arguments);
+      }
+      setBindData(bound, bindData);
+      return bound;
+    }
+
+    /**
+     * The base implementation of `_.clone` without argument juggling or support
+     * for `thisArg` binding.
+     *
+     * @private
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep=false] Specify a deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates clones with source counterparts.
+     * @returns {*} Returns the cloned value.
+     */
+    function baseClone(value, isDeep, callback, stackA, stackB) {
+      if (callback) {
+        var result = callback(value);
+        if (typeof result != 'undefined') {
+          return result;
+        }
+      }
+      // inspect [[Class]]
+      var isObj = isObject(value);
+      if (isObj) {
+        var className = toString.call(value);
+        if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) {
+          return value;
+        }
+        var ctor = ctorByClass[className];
+        switch (className) {
+          case boolClass:
+          case dateClass:
+            return new ctor(+value);
+
+          case numberClass:
+          case stringClass:
+            return new ctor(value);
+
+          case regexpClass:
+            result = ctor(value.source, reFlags.exec(value));
+            result.lastIndex = value.lastIndex;
+            return result;
+        }
+      } else {
+        return value;
+      }
+      var isArr = isArray(value);
+      if (isDeep) {
+        // check for circular references and return corresponding clone
+        var initedStack = !stackA;
+        stackA || (stackA = getArray());
+        stackB || (stackB = getArray());
+
+        var length = stackA.length;
+        while (length--) {
+          if (stackA[length] == value) {
+            return stackB[length];
+          }
+        }
+        result = isArr ? ctor(value.length) : {};
+      }
+      else {
+        result = isArr ? slice(value) : assign({}, value);
+      }
+      // add array properties assigned by `RegExp#exec`
+      if (isArr) {
+        if (hasOwnProperty.call(value, 'index')) {
+          result.index = value.index;
+        }
+        if (hasOwnProperty.call(value, 'input')) {
+          result.input = value.input;
+        }
+      }
+      // exit for shallow clone
+      if (!isDeep) {
+        return result;
+      }
+      // add the source value to the stack of traversed objects
+      // and associate it with its clone
+      stackA.push(value);
+      stackB.push(result);
+
+      // recursively populate clone (susceptible to call stack limits)
+      (isArr ? baseEach : forOwn)(value, function(objValue, key) {
+        result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
+      });
+
+      if (initedStack) {
+        releaseArray(stackA);
+        releaseArray(stackB);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.create` without support for assigning
+     * properties to the created object.
+     *
+     * @private
+     * @param {Object} prototype The object to inherit from.
+     * @returns {Object} Returns the new object.
+     */
+    function baseCreate(prototype, properties) {
+      return isObject(prototype) ? nativeCreate(prototype) : {};
+    }
+    // fallback for browsers without `Object.create`
+    if (!nativeCreate) {
+      baseCreate = (function() {
+        function Object() {}
+        return function(prototype) {
+          if (isObject(prototype)) {
+            Object.prototype = prototype;
+            var result = new Object;
+            Object.prototype = null;
+          }
+          return result || context.Object();
+        };
+      }());
+    }
+
+    /**
+     * The base implementation of `_.createCallback` without support for creating
+     * "_.pluck" or "_.where" style callbacks.
+     *
+     * @private
+     * @param {*} [func=identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of the created callback.
+     * @param {number} [argCount] The number of arguments the callback accepts.
+     * @returns {Function} Returns a callback function.
+     */
+    function baseCreateCallback(func, thisArg, argCount) {
+      if (typeof func != 'function') {
+        return identity;
+      }
+      // exit early for no `thisArg` or already bound by `Function#bind`
+      if (typeof thisArg == 'undefined' || !('prototype' in func)) {
+        return func;
+      }
+      var bindData = func.__bindData__;
+      if (typeof bindData == 'undefined') {
+        if (support.funcNames) {
+          bindData = !func.name;
+        }
+        bindData = bindData || !support.funcDecomp;
+        if (!bindData) {
+          var source = fnToString.call(func);
+          if (!support.funcNames) {
+            bindData = !reFuncName.test(source);
+          }
+          if (!bindData) {
+            // checks if `func` references the `this` keyword and stores the result
+            bindData = reThis.test(source);
+            setBindData(func, bindData);
+          }
+        }
+      }
+      // exit early if there are no `this` references or `func` is bound
+      if (bindData === false || (bindData !== true && bindData[1] & 1)) {
+        return func;
+      }
+      switch (argCount) {
+        case 1: return function(value) {
+          return func.call(thisArg, value);
+        };
+        case 2: return function(a, b) {
+          return func.call(thisArg, a, b);
+        };
+        case 3: return function(value, index, collection) {
+          return func.call(thisArg, value, index, collection);
+        };
+        case 4: return function(accumulator, value, index, collection) {
+          return func.call(thisArg, accumulator, value, index, collection);
+        };
+      }
+      return bind(func, thisArg);
+    }
+
+    /**
+     * The base implementation of `createWrapper` that creates the wrapper and
+     * sets its meta data.
+     *
+     * @private
+     * @param {Array} bindData The bind data array.
+     * @returns {Function} Returns the new function.
+     */
+    function baseCreateWrapper(bindData) {
+      var func = bindData[0],
+          bitmask = bindData[1],
+          partialArgs = bindData[2],
+          partialRightArgs = bindData[3],
+          thisArg = bindData[4],
+          arity = bindData[5];
+
+      var isBind = bitmask & 1,
+          isBindKey = bitmask & 2,
+          isCurry = bitmask & 4,
+          isCurryBound = bitmask & 8,
+          key = func;
+
+      function bound() {
+        var thisBinding = isBind ? thisArg : this;
+        if (partialArgs) {
+          var args = slice(partialArgs);
+          push.apply(args, arguments);
+        }
+        if (partialRightArgs || isCurry) {
+          args || (args = slice(arguments));
+          if (partialRightArgs) {
+            push.apply(args, partialRightArgs);
+          }
+          if (isCurry && args.length < arity) {
+            bitmask |= 16 & ~32;
+            return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
+          }
+        }
+        args || (args = arguments);
+        if (isBindKey) {
+          func = thisBinding[key];
+        }
+        if (this instanceof bound) {
+          thisBinding = baseCreate(func.prototype);
+          var result = func.apply(thisBinding, args);
+          return isObject(result) ? result : thisBinding;
+        }
+        return func.apply(thisBinding, args);
+      }
+      setBindData(bound, bindData);
+      return bound;
+    }
+
+    /**
+     * The base implementation of `_.difference` that accepts a single array
+     * of values to exclude.
+     *
+     * @private
+     * @param {Array} array The array to process.
+     * @param {Array} [values] The array of values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     */
+    function baseDifference(array, values) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array ? array.length : 0,
+          isLarge = length >= largeArraySize && indexOf === baseIndexOf,
+          result = [];
+
+      if (isLarge) {
+        var cache = createCache(values);
+        if (cache) {
+          indexOf = cacheIndexOf;
+          values = cache;
+        } else {
+          isLarge = false;
+        }
+      }
+      while (++index < length) {
+        var value = array[index];
+        if (indexOf(values, value) < 0) {
+          result.push(value);
+        }
+      }
+      if (isLarge) {
+        releaseObject(values);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.flatten` without support for callback
+     * shorthands or `thisArg` binding.
+     *
+     * @private
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+     * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
+     * @param {number} [fromIndex=0] The index to start from.
+     * @returns {Array} Returns a new flattened array.
+     */
+    function baseFlatten(array, isShallow, isStrict, fromIndex) {
+      var index = (fromIndex || 0) - 1,
+          length = array ? array.length : 0,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+
+        if (value && typeof value == 'object' && typeof value.length == 'number'
+            && (isArray(value) || isArguments(value))) {
+          // recursively flatten arrays (susceptible to call stack limits)
+          if (!isShallow) {
+            value = baseFlatten(value, isShallow, isStrict);
+          }
+          var valIndex = -1,
+              valLength = value.length,
+              resIndex = result.length;
+
+          result.length += valLength;
+          while (++valIndex < valLength) {
+            result[resIndex++] = value[valIndex];
+          }
+        } else if (!isStrict) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.isEqual`, without support for `thisArg` binding,
+     * that allows partial "_.where" style comparisons.
+     *
+     * @private
+     * @param {*} a The value to compare.
+     * @param {*} b The other value to compare.
+     * @param {Function} [callback] The function to customize comparing values.
+     * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
+     * @param {Array} [stackA=[]] Tracks traversed `a` objects.
+     * @param {Array} [stackB=[]] Tracks traversed `b` objects.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     */
+    function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
+      // used to indicate that when comparing objects, `a` has at least the properties of `b`
+      if (callback) {
+        var result = callback(a, b);
+        if (typeof result != 'undefined') {
+          return !!result;
+        }
+      }
+      // exit early for identical values
+      if (a === b) {
+        // treat `+0` vs. `-0` as not equal
+        return a !== 0 || (1 / a == 1 / b);
+      }
+      var type = typeof a,
+          otherType = typeof b;
+
+      // exit early for unlike primitive values
+      if (a === a &&
+          !(a && objectTypes[type]) &&
+          !(b && objectTypes[otherType])) {
+        return false;
+      }
+      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
+      // http://es5.github.io/#x15.3.4.4
+      if (a == null || b == null) {
+        return a === b;
+      }
+      // compare [[Class]] names
+      var className = toString.call(a),
+          otherClass = toString.call(b);
+
+      if (className == argsClass) {
+        className = objectClass;
+      }
+      if (otherClass == argsClass) {
+        otherClass = objectClass;
+      }
+      if (className != otherClass) {
+        return false;
+      }
+      switch (className) {
+        case boolClass:
+        case dateClass:
+          // coerce dates and booleans to numbers, dates to milliseconds and booleans
+          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
+          return +a == +b;
+
+        case numberClass:
+          // treat `NaN` vs. `NaN` as equal
+          return (a != +a)
+            ? b != +b
+            // but treat `+0` vs. `-0` as not equal
+            : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+        case regexpClass:
+        case stringClass:
+          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
+          // treat string primitives and their corresponding object instances as equal
+          return a == String(b);
+      }
+      var isArr = className == arrayClass;
+      if (!isArr) {
+        // unwrap any `lodash` wrapped values
+        var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
+            bWrapped = hasOwnProperty.call(b, '__wrapped__');
+
+        if (aWrapped || bWrapped) {
+          return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
+        }
+        // exit for functions and DOM nodes
+        if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {
+          return false;
+        }
+        // in older versions of Opera, `arguments` objects have `Array` constructors
+        var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,
+            ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
+
+        // non `Object` object instances with different constructors are not equal
+        if (ctorA != ctorB &&
+              !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
+              ('constructor' in a && 'constructor' in b)
+            ) {
+          return false;
+        }
+      }
+      // assume cyclic structures are equal
+      // the algorithm for detecting cyclic structures is adapted from ES 5.1
+      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
+      var initedStack = !stackA;
+      stackA || (stackA = getArray());
+      stackB || (stackB = getArray());
+
+      var length = stackA.length;
+      while (length--) {
+        if (stackA[length] == a) {
+          return stackB[length] == b;
+        }
+      }
+      var size = 0;
+      result = true;
+
+      // add `a` and `b` to the stack of traversed objects
+      stackA.push(a);
+      stackB.push(b);
+
+      // recursively compare objects and arrays (susceptible to call stack limits)
+      if (isArr) {
+        // compare lengths to determine if a deep comparison is necessary
+        length = a.length;
+        size = b.length;
+        result = size == length;
+
+        if (result || isWhere) {
+          // deep compare the contents, ignoring non-numeric properties
+          while (size--) {
+            var index = length,
+                value = b[size];
+
+            if (isWhere) {
+              while (index--) {
+                if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
+                  break;
+                }
+              }
+            } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
+              break;
+            }
+          }
+        }
+      }
+      else {
+        // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
+        // which, in this case, is more costly
+        forIn(b, function(value, key, b) {
+          if (hasOwnProperty.call(b, key)) {
+            // count the number of properties.
+            size++;
+            // deep compare each property value.
+            return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
+          }
+        });
+
+        if (result && !isWhere) {
+          // ensure both objects have the same number of properties
+          forIn(a, function(value, key, a) {
+            if (hasOwnProperty.call(a, key)) {
+              // `size` will be `-1` if `a` has more properties than `b`
+              return (result = --size > -1);
+            }
+          });
+        }
+      }
+      stackA.pop();
+      stackB.pop();
+
+      if (initedStack) {
+        releaseArray(stackA);
+        releaseArray(stackB);
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.merge` without argument juggling or support
+     * for `thisArg` binding.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @param {Function} [callback] The function to customize merging properties.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates values with source counterparts.
+     */
+    function baseMerge(object, source, callback, stackA, stackB) {
+      (isArray(source) ? forEach : forOwn)(source, function(source, key) {
+        var found,
+            isArr,
+            result = source,
+            value = object[key];
+
+        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+          // avoid merging previously merged cyclic sources
+          var stackLength = stackA.length;
+          while (stackLength--) {
+            if ((found = stackA[stackLength] == source)) {
+              value = stackB[stackLength];
+              break;
+            }
+          }
+          if (!found) {
+            var isShallow;
+            if (callback) {
+              result = callback(value, source);
+              if ((isShallow = typeof result != 'undefined')) {
+                value = result;
+              }
+            }
+            if (!isShallow) {
+              value = isArr
+                ? (isArray(value) ? value : [])
+                : (isPlainObject(value) ? value : {});
+            }
+            // add `source` and associated `value` to the stack of traversed objects
+            stackA.push(source);
+            stackB.push(value);
+
+            // recursively merge objects and arrays (susceptible to call stack limits)
+            if (!isShallow) {
+              baseMerge(value, source, callback, stackA, stackB);
+            }
+          }
+        }
+        else {
+          if (callback) {
+            result = callback(value, source);
+            if (typeof result == 'undefined') {
+              result = source;
+            }
+          }
+          if (typeof result != 'undefined') {
+            value = result;
+          }
+        }
+        object[key] = value;
+      });
+    }
+
+    /**
+     * The base implementation of `_.random` without argument juggling or support
+     * for returning floating-point numbers.
+     *
+     * @private
+     * @param {number} min The minimum possible value.
+     * @param {number} max The maximum possible value.
+     * @returns {number} Returns a random number.
+     */
+    function baseRandom(min, max) {
+      return min + floor(nativeRandom() * (max - min + 1));
+    }
+
+    /**
+     * The base implementation of `_.uniq` without support for callback shorthands
+     * or `thisArg` binding.
+     *
+     * @private
+     * @param {Array} array The array to process.
+     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+     * @param {Function} [callback] The function called per iteration.
+     * @returns {Array} Returns a duplicate-value-free array.
+     */
+    function baseUniq(array, isSorted, callback) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array ? array.length : 0,
+          result = [];
+
+      var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
+          seen = (callback || isLarge) ? getArray() : result;
+
+      if (isLarge) {
+        var cache = createCache(seen);
+        indexOf = cacheIndexOf;
+        seen = cache;
+      }
+      while (++index < length) {
+        var value = array[index],
+            computed = callback ? callback(value, index, array) : value;
+
+        if (isSorted
+              ? !index || seen[seen.length - 1] !== computed
+              : indexOf(seen, computed) < 0
+            ) {
+          if (callback || isLarge) {
+            seen.push(computed);
+          }
+          result.push(value);
+        }
+      }
+      if (isLarge) {
+        releaseArray(seen.array);
+        releaseObject(seen);
+      } else if (callback) {
+        releaseArray(seen);
+      }
+      return result;
+    }
+
+    /**
+     * Creates a function that aggregates a collection, creating an object composed
+     * of keys generated from the results of running each element of the collection
+     * through a callback. The given `setter` function sets the keys and values
+     * of the composed object.
+     *
+     * @private
+     * @param {Function} setter The setter function.
+     * @returns {Function} Returns the new aggregator function.
+     */
+    function createAggregator(setter) {
+      return function(collection, callback, thisArg) {
+        var result = {};
+        callback = lodash.createCallback(callback, thisArg, 3);
+
+        if (isArray(collection)) {
+          var index = -1,
+              length = collection.length;
+
+          while (++index < length) {
+            var value = collection[index];
+            setter(result, value, callback(value, index, collection), collection);
+          }
+        } else {
+          baseEach(collection, function(value, key, collection) {
+            setter(result, value, callback(value, key, collection), collection);
+          });
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that, when called, either curries or invokes `func`
+     * with an optional `this` binding and partially applied arguments.
+     *
+     * @private
+     * @param {Function|string} func The function or method name to reference.
+     * @param {number} bitmask The bitmask of method flags to compose.
+     *  The bitmask may be composed of the following flags:
+     *  1 - `_.bind`
+     *  2 - `_.bindKey`
+     *  4 - `_.curry`
+     *  8 - `_.curry` (bound)
+     *  16 - `_.partial`
+     *  32 - `_.partialRight`
+     * @param {Array} [partialArgs] An array of arguments to prepend to those
+     *  provided to the new function.
+     * @param {Array} [partialRightArgs] An array of arguments to append to those
+     *  provided to the new function.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {number} [arity] The arity of `func`.
+     * @returns {Function} Returns the new function.
+     */
+    function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
+      var isBind = bitmask & 1,
+          isBindKey = bitmask & 2,
+          isCurry = bitmask & 4,
+          isCurryBound = bitmask & 8,
+          isPartial = bitmask & 16,
+          isPartialRight = bitmask & 32;
+
+      if (!isBindKey && !isFunction(func)) {
+        throw new TypeError;
+      }
+      if (isPartial && !partialArgs.length) {
+        bitmask &= ~16;
+        isPartial = partialArgs = false;
+      }
+      if (isPartialRight && !partialRightArgs.length) {
+        bitmask &= ~32;
+        isPartialRight = partialRightArgs = false;
+      }
+      var bindData = func && func.__bindData__;
+      if (bindData && bindData !== true) {
+        // clone `bindData`
+        bindData = slice(bindData);
+        if (bindData[2]) {
+          bindData[2] = slice(bindData[2]);
+        }
+        if (bindData[3]) {
+          bindData[3] = slice(bindData[3]);
+        }
+        // set `thisBinding` is not previously bound
+        if (isBind && !(bindData[1] & 1)) {
+          bindData[4] = thisArg;
+        }
+        // set if previously bound but not currently (subsequent curried functions)
+        if (!isBind && bindData[1] & 1) {
+          bitmask |= 8;
+        }
+        // set curried arity if not yet set
+        if (isCurry && !(bindData[1] & 4)) {
+          bindData[5] = arity;
+        }
+        // append partial left arguments
+        if (isPartial) {
+          push.apply(bindData[2] || (bindData[2] = []), partialArgs);
+        }
+        // append partial right arguments
+        if (isPartialRight) {
+          unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
+        }
+        // merge flags
+        bindData[1] |= bitmask;
+        return createWrapper.apply(null, bindData);
+      }
+      // fast path for `_.bind`
+      var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
+      return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
+    }
+
+    /**
+     * Creates compiled iteration functions.
+     *
+     * @private
+     * @param {...Object} [options] The compile options object(s).
+     * @param {string} [options.array] Code to determine if the iterable is an array or array-like.
+     * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop.
+     * @param {Function} [options.keys] A reference to `_.keys` for use in own property iteration.
+     * @param {string} [options.args] A comma separated string of iteration function arguments.
+     * @param {string} [options.top] Code to execute before the iteration branches.
+     * @param {string} [options.loop] Code to execute in the object loop.
+     * @param {string} [options.bottom] Code to execute after the iteration branches.
+     * @returns {Function} Returns the compiled function.
+     */
+    function createIterator() {
+      // data properties
+      iteratorData.shadowedProps = shadowedProps;
+      iteratorData.support = support;
+
+      // iterator options
+      iteratorData.array = iteratorData.bottom = iteratorData.loop = iteratorData.top = '';
+      iteratorData.init = 'iterable';
+      iteratorData.useHas = true;
+
+      // merge options into a template data object
+      for (var object, index = 0; object = arguments[index]; index++) {
+        for (var key in object) {
+          iteratorData[key] = object[key];
+        }
+      }
+      var args = iteratorData.args;
+      iteratorData.firstArg = /^[^,]+/.exec(args)[0];
+
+      // create the function factory
+      var factory = Function(
+          'baseCreateCallback, errorClass, errorProto, hasOwnProperty, ' +
+          'indicatorObject, isArguments, isArray, isString, keys, objectProto, ' +
+          'objectTypes, nonEnumProps, stringClass, stringProto, toString',
+        'return function(' + args + ') {\n' + iteratorTemplate(iteratorData) + '\n}'
+      );
+
+      // return the compiled function
+      return factory(
+        baseCreateCallback, errorClass, errorProto, hasOwnProperty,
+        indicatorObject, isArguments, isArray, isString, iteratorData.keys, objectProto,
+        objectTypes, nonEnumProps, stringClass, stringProto, toString
+      );
+    }
+
+    /**
+     * Used by `escape` to convert characters to HTML entities.
+     *
+     * @private
+     * @param {string} match The matched character to escape.
+     * @returns {string} Returns the escaped character.
+     */
+    function escapeHtmlChar(match) {
+      return htmlEscapes[match];
+    }
+
+    /**
+     * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+     * customized, this method returns the custom method, otherwise it returns
+     * the `baseIndexOf` function.
+     *
+     * @private
+     * @returns {Function} Returns the "indexOf" function.
+     */
+    function getIndexOf() {
+      var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
+      return result;
+    }
+
+    /**
+     * Checks if `value` is a native function.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
+     */
+    function isNative(value) {
+      return typeof value == 'function' && reNative.test(value);
+    }
+
+    /**
+     * Sets `this` binding data on a given function.
+     *
+     * @private
+     * @param {Function} func The function to set data on.
+     * @param {Array} value The data array to set.
+     */
+    var setBindData = !defineProperty ? noop : function(func, value) {
+      descriptor.value = value;
+      defineProperty(func, '__bindData__', descriptor);
+    };
+
+    /**
+     * A fallback implementation of `isPlainObject` which checks if a given value
+     * is an object created by the `Object` constructor, assuming objects created
+     * by the `Object` constructor have no inherited enumerable properties and that
+     * there are no `Object.prototype` extensions.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     */
+    function shimIsPlainObject(value) {
+      var ctor,
+          result;
+
+      // avoid non Object objects, `arguments` objects, and DOM elements
+      if (!(value && toString.call(value) == objectClass) ||
+          (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor)) ||
+          (!support.argsClass && isArguments(value)) ||
+          (!support.nodeClass && isNode(value))) {
+        return false;
+      }
+      // IE < 9 iterates inherited properties before own properties. If the first
+      // iterated property is an object's own property then there are no inherited
+      // enumerable properties.
+      if (support.ownLast) {
+        forIn(value, function(value, key, object) {
+          result = hasOwnProperty.call(object, key);
+          return false;
+        });
+        return result !== false;
+      }
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      forIn(value, function(value, key) {
+        result = key;
+      });
+      return typeof result == 'undefined' || hasOwnProperty.call(value, result);
+    }
+
+    /**
+     * Used by `unescape` to convert HTML entities to characters.
+     *
+     * @private
+     * @param {string} match The matched character to unescape.
+     * @returns {string} Returns the unescaped character.
+     */
+    function unescapeHtmlChar(match) {
+      return htmlUnescapes[match];
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Checks if `value` is an `arguments` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+     * @example
+     *
+     * (function() { return _.isArguments(arguments); })(1, 2, 3);
+     * // => true
+     *
+     * _.isArguments([1, 2, 3]);
+     * // => false
+     */
+    function isArguments(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        toString.call(value) == argsClass || false;
+    }
+    // fallback for browsers that can't detect `arguments` objects by [[Class]]
+    if (!support.argsClass) {
+      isArguments = function(value) {
+        return value && typeof value == 'object' && typeof value.length == 'number' &&
+          hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false;
+      };
+    }
+
+    /**
+     * Checks if `value` is an array.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
+     * @example
+     *
+     * (function() { return _.isArray(arguments); })();
+     * // => false
+     *
+     * _.isArray([1, 2, 3]);
+     * // => true
+     */
+    var isArray = nativeIsArray || function(value) {
+      return value && typeof value == 'object' && typeof value.length == 'number' &&
+        toString.call(value) == arrayClass || false;
+    };
+
+    /**
+     * A fallback implementation of `Object.keys` which produces an array of the
+     * given object's own enumerable property names.
+     *
+     * @private
+     * @type Function
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names.
+     */
+    var shimKeys = createIterator({
+      'args': 'object',
+      'init': '[]',
+      'top': 'if (!(objectTypes[typeof object])) return result',
+      'loop': 'result.push(index)'
+    });
+
+    /**
+     * Creates an array composed of the own enumerable property names of an object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names.
+     * @example
+     *
+     * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
+     */
+    var keys = !nativeKeys ? shimKeys : function(object) {
+      if (!isObject(object)) {
+        return [];
+      }
+      if ((support.enumPrototypes && typeof object == 'function') ||
+          (support.nonEnumArgs && object.length && isArguments(object))) {
+        return shimKeys(object);
+      }
+      return nativeKeys(object);
+    };
+
+    /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
+    var eachIteratorOptions = {
+      'args': 'collection, callback, thisArg',
+      'top': "callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",
+      'array': "typeof length == 'number'",
+      'keys': keys,
+      'loop': 'if (callback(iterable[index], index, collection) === false) return result'
+    };
+
+    /** Reusable iterator options for `assign` and `defaults` */
+    var defaultsIteratorOptions = {
+      'args': 'object, source, guard',
+      'top':
+        'var args = arguments,\n' +
+        '    argsIndex = 0,\n' +
+        "    argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
+        'while (++argsIndex < argsLength) {\n' +
+        '  iterable = args[argsIndex];\n' +
+        '  if (iterable && objectTypes[typeof iterable]) {',
+      'keys': keys,
+      'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
+      'bottom': '  }\n}'
+    };
+
+    /** Reusable iterator options for `forIn` and `forOwn` */
+    var forOwnIteratorOptions = {
+      'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
+      'array': false
+    };
+
+    /**
+     * Used to convert characters to HTML entities:
+     *
+     * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+     * don't require escaping in HTML and have no special meaning unless they're part
+     * of a tag or an unquoted attribute value.
+     * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+     */
+    var htmlEscapes = {
+      '&': '&amp;',
+      '<': '&lt;',
+      '>': '&gt;',
+      '"': '&quot;',
+      "'": '&#39;'
+    };
+
+    /** Used to convert HTML entities to characters */
+    var htmlUnescapes = invert(htmlEscapes);
+
+    /** Used to match HTML entities and HTML characters */
+    var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
+        reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
+
+    /**
+     * A function compiled to iterate `arguments` objects, arrays, objects, and
+     * strings consistenly across environments, executing the callback for each
+     * element in the collection. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index|key, collection). Callbacks may exit
+     * iteration early by explicitly returning `false`.
+     *
+     * @private
+     * @type Function
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     */
+    var baseEach = createIterator(eachIteratorOptions);
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object. Subsequent sources will overwrite property assignments of previous
+     * sources. If a callback is provided it will be executed to produce the
+     * assigned values. The callback is bound to `thisArg` and invoked with two
+     * arguments; (objectValue, sourceValue).
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @alias extend
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param {Function} [callback] The function to customize assigning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
+     * // => { 'name': 'fred', 'employer': 'slate' }
+     *
+     * var defaults = _.partialRight(_.assign, function(a, b) {
+     *   return typeof a == 'undefined' ? b : a;
+     * });
+     *
+     * var object = { 'name': 'barney' };
+     * defaults(object, { 'name': 'fred', 'employer': 'slate' });
+     * // => { 'name': 'barney', 'employer': 'slate' }
+     */
+    var assign = createIterator(defaultsIteratorOptions, {
+      'top':
+        defaultsIteratorOptions.top.replace(';',
+          ';\n' +
+          "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
+          '  var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
+          "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
+          '  callback = args[--argsLength];\n' +
+          '}'
+        ),
+      'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
+    });
+
+    /**
+     * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
+     * be cloned, otherwise they will be assigned by reference. If a callback
+     * is provided it will be executed to produce the cloned values. If the
+     * callback returns `undefined` cloning will be handled by the method instead.
+     * The callback is bound to `thisArg` and invoked with one argument; (value).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep=false] Specify a deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the cloned value.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * var shallow = _.clone(characters);
+     * shallow[0] === characters[0];
+     * // => true
+     *
+     * var deep = _.clone(characters, true);
+     * deep[0] === characters[0];
+     * // => false
+     *
+     * _.mixin({
+     *   'clone': _.partialRight(_.clone, function(value) {
+     *     return _.isElement(value) ? value.cloneNode(false) : undefined;
+     *   })
+     * });
+     *
+     * var clone = _.clone(document.body);
+     * clone.childNodes.length;
+     * // => 0
+     */
+    function clone(value, isDeep, callback, thisArg) {
+      // allows working with "Collections" methods without using their `index`
+      // and `collection` arguments for `isDeep` and `callback`
+      if (typeof isDeep != 'boolean' && isDeep != null) {
+        thisArg = callback;
+        callback = isDeep;
+        isDeep = false;
+      }
+      return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+    }
+
+    /**
+     * Creates a deep clone of `value`. If a callback is provided it will be
+     * executed to produce the cloned values. If the callback returns `undefined`
+     * cloning will be handled by the method instead. The callback is bound to
+     * `thisArg` and invoked with one argument; (value).
+     *
+     * Note: This method is loosely based on the structured clone algorithm. Functions
+     * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+     * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+     * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to deep clone.
+     * @param {Function} [callback] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the deep cloned value.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * var deep = _.cloneDeep(characters);
+     * deep[0] === characters[0];
+     * // => false
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'node': element
+     * };
+     *
+     * var clone = _.cloneDeep(view, function(value) {
+     *   return _.isElement(value) ? value.cloneNode(true) : undefined;
+     * });
+     *
+     * clone.node == view.node;
+     * // => false
+     */
+    function cloneDeep(value, callback, thisArg) {
+      return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+    }
+
+    /**
+     * Creates an object that inherits from the given `prototype` object. If a
+     * `properties` object is provided its own enumerable properties are assigned
+     * to the created object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} prototype The object to inherit from.
+     * @param {Object} [properties] The properties to assign to the object.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * function Circle() {
+     *   Shape.call(this);
+     * }
+     *
+     * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
+     *
+     * var circle = new Circle;
+     * circle instanceof Circle;
+     * // => true
+     *
+     * circle instanceof Shape;
+     * // => true
+     */
+    function create(prototype, properties) {
+      var result = baseCreate(prototype);
+      return properties ? assign(result, properties) : result;
+    }
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object for all destination properties that resolve to `undefined`. Once a
+     * property is set, additional defaults of the same property will be ignored.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param- {Object} [guard] Allows working with `_.reduce` without using its
+     *  `key` and `object` arguments as sources.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * var object = { 'name': 'barney' };
+     * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
+     * // => { 'name': 'barney', 'employer': 'slate' }
+     */
+    var defaults = createIterator(defaultsIteratorOptions);
+
+    /**
+     * This method is like `_.findIndex` except that it returns the key of the
+     * first element that passes the callback check, instead of the element itself.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [callback=identity] The function called per
+     *  iteration. If a property name or object is provided it will be used to
+     *  create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
+     * @example
+     *
+     * var characters = {
+     *   'barney': {  'age': 36, 'blocked': false },
+     *   'fred': {    'age': 40, 'blocked': true },
+     *   'pebbles': { 'age': 1,  'blocked': false }
+     * };
+     *
+     * _.findKey(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => 'barney' (property order is not guaranteed across environments)
+     *
+     * // using "_.where" callback shorthand
+     * _.findKey(characters, { 'age': 1 });
+     * // => 'pebbles'
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findKey(characters, 'blocked');
+     * // => 'fred'
+     */
+    function findKey(object, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forOwn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result = key;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * This method is like `_.findKey` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [callback=identity] The function called per
+     *  iteration. If a property name or object is provided it will be used to
+     *  create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
+     * @example
+     *
+     * var characters = {
+     *   'barney': {  'age': 36, 'blocked': true },
+     *   'fred': {    'age': 40, 'blocked': false },
+     *   'pebbles': { 'age': 1,  'blocked': true }
+     * };
+     *
+     * _.findLastKey(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => returns `pebbles`, assuming `_.findKey` returns `barney`
+     *
+     * // using "_.where" callback shorthand
+     * _.findLastKey(characters, { 'age': 40 });
+     * // => 'fred'
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findLastKey(characters, 'blocked');
+     * // => 'pebbles'
+     */
+    function findLastKey(object, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forOwnRight(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result = key;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Iterates over own and inherited enumerable properties of an object,
+     * executing the callback for each property. The callback is bound to `thisArg`
+     * and invoked with three arguments; (value, key, object). Callbacks may exit
+     * iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * Shape.prototype.move = function(x, y) {
+     *   this.x += x;
+     *   this.y += y;
+     * };
+     *
+     * _.forIn(new Shape, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
+     */
+    var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
+      'useHas': false
+    });
+
+    /**
+     * This method is like `_.forIn` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * Shape.prototype.move = function(x, y) {
+     *   this.x += x;
+     *   this.y += y;
+     * };
+     *
+     * _.forInRight(new Shape, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
+     */
+    function forInRight(object, callback, thisArg) {
+      var pairs = [];
+
+      forIn(object, function(value, key) {
+        pairs.push(key, value);
+      });
+
+      var length = pairs.length;
+      callback = baseCreateCallback(callback, thisArg, 3);
+      while (length--) {
+        if (callback(pairs[length--], pairs[length], object) === false) {
+          break;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Iterates over own enumerable properties of an object, executing the callback
+     * for each property. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, key, object). Callbacks may exit iteration early by
+     * explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+     *   console.log(key);
+     * });
+     * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
+     */
+    var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
+
+    /**
+     * This method is like `_.forOwn` except that it iterates over elements
+     * of a `collection` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
+     */
+    function forOwnRight(object, callback, thisArg) {
+      var props = keys(object),
+          length = props.length;
+
+      callback = baseCreateCallback(callback, thisArg, 3);
+      while (length--) {
+        var key = props[length];
+        if (callback(object[key], key, object) === false) {
+          break;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Creates a sorted array of property names of all enumerable properties,
+     * own and inherited, of `object` that have function values.
+     *
+     * @static
+     * @memberOf _
+     * @alias methods
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property names that have function values.
+     * @example
+     *
+     * _.functions(_);
+     * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+     */
+    function functions(object) {
+      var result = [];
+      forIn(object, function(value, key) {
+        if (isFunction(value)) {
+          result.push(key);
+        }
+      });
+      return result.sort();
+    }
+
+    /**
+     * Checks if the specified property name exists as a direct property of `object`,
+     * instead of an inherited property.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @param {string} key The name of the property to check.
+     * @returns {boolean} Returns `true` if key is a direct property, else `false`.
+     * @example
+     *
+     * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+     * // => true
+     */
+    function has(object, key) {
+      return object ? hasOwnProperty.call(object, key) : false;
+    }
+
+    /**
+     * Creates an object composed of the inverted keys and values of the given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to invert.
+     * @returns {Object} Returns the created inverted object.
+     * @example
+     *
+     * _.invert({ 'first': 'fred', 'second': 'barney' });
+     * // => { 'fred': 'first', 'barney': 'second' }
+     */
+    function invert(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = {};
+
+      while (++index < length) {
+        var key = props[index];
+        result[object[key]] = key;
+      }
+      return result;
+    }
+
+    /**
+     * Checks if `value` is a boolean value.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
+     * @example
+     *
+     * _.isBoolean(null);
+     * // => false
+     */
+    function isBoolean(value) {
+      return value === true || value === false ||
+        value && typeof value == 'object' && toString.call(value) == boolClass || false;
+    }
+
+    /**
+     * Checks if `value` is a date.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
+     * @example
+     *
+     * _.isDate(new Date);
+     * // => true
+     */
+    function isDate(value) {
+      return value && typeof value == 'object' && toString.call(value) == dateClass || false;
+    }
+
+    /**
+     * Checks if `value` is a DOM element.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
+     * @example
+     *
+     * _.isElement(document.body);
+     * // => true
+     */
+    function isElement(value) {
+      return value && value.nodeType === 1 || false;
+    }
+
+    /**
+     * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+     * length of `0` and objects with no own enumerable properties are considered
+     * "empty".
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Array|Object|string} value The value to inspect.
+     * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
+     * @example
+     *
+     * _.isEmpty([1, 2, 3]);
+     * // => false
+     *
+     * _.isEmpty({});
+     * // => true
+     *
+     * _.isEmpty('');
+     * // => true
+     */
+    function isEmpty(value) {
+      var result = true;
+      if (!value) {
+        return result;
+      }
+      var className = toString.call(value),
+          length = value.length;
+
+      if ((className == arrayClass || className == stringClass ||
+          (support.argsClass ? className == argsClass : isArguments(value))) ||
+          (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+        return !length;
+      }
+      forOwn(value, function() {
+        return (result = false);
+      });
+      return result;
+    }
+
+    /**
+     * Performs a deep comparison between two values to determine if they are
+     * equivalent to each other. If a callback is provided it will be executed
+     * to compare values. If the callback returns `undefined` comparisons will
+     * be handled by the method instead. The callback is bound to `thisArg` and
+     * invoked with two arguments; (a, b).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} a The value to compare.
+     * @param {*} b The other value to compare.
+     * @param {Function} [callback] The function to customize comparing values.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * var copy = { 'name': 'fred' };
+     *
+     * object == copy;
+     * // => false
+     *
+     * _.isEqual(object, copy);
+     * // => true
+     *
+     * var words = ['hello', 'goodbye'];
+     * var otherWords = ['hi', 'goodbye'];
+     *
+     * _.isEqual(words, otherWords, function(a, b) {
+     *   var reGreet = /^(?:hello|hi)$/i,
+     *       aGreet = _.isString(a) && reGreet.test(a),
+     *       bGreet = _.isString(b) && reGreet.test(b);
+     *
+     *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+     * });
+     * // => true
+     */
+    function isEqual(a, b, callback, thisArg) {
+      return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
+    }
+
+    /**
+     * Checks if `value` is, or can be coerced to, a finite number.
+     *
+     * Note: This is not the same as native `isFinite` which will return true for
+     * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
+     * @example
+     *
+     * _.isFinite(-101);
+     * // => true
+     *
+     * _.isFinite('10');
+     * // => true
+     *
+     * _.isFinite(true);
+     * // => false
+     *
+     * _.isFinite('');
+     * // => false
+     *
+     * _.isFinite(Infinity);
+     * // => false
+     */
+    function isFinite(value) {
+      return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+    }
+
+    /**
+     * Checks if `value` is a function.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
+     * @example
+     *
+     * _.isFunction(_);
+     * // => true
+     */
+    function isFunction(value) {
+      return typeof value == 'function';
+    }
+    // fallback for older versions of Chrome and Safari
+    if (isFunction(/x/)) {
+      isFunction = function(value) {
+        return typeof value == 'function' && toString.call(value) == funcClass;
+      };
+    }
+
+    /**
+     * Checks if `value` is the language type of Object.
+     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
+     * @example
+     *
+     * _.isObject({});
+     * // => true
+     *
+     * _.isObject([1, 2, 3]);
+     * // => true
+     *
+     * _.isObject(1);
+     * // => false
+     */
+    function isObject(value) {
+      // check if the value is the ECMAScript language type of Object
+      // http://es5.github.io/#x8
+      // and avoid a V8 bug
+      // http://code.google.com/p/v8/issues/detail?id=2291
+      return !!(value && objectTypes[typeof value]);
+    }
+
+    /**
+     * Checks if `value` is `NaN`.
+     *
+     * Note: This is not the same as native `isNaN` which will return `true` for
+     * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
+     * @example
+     *
+     * _.isNaN(NaN);
+     * // => true
+     *
+     * _.isNaN(new Number(NaN));
+     * // => true
+     *
+     * isNaN(undefined);
+     * // => true
+     *
+     * _.isNaN(undefined);
+     * // => false
+     */
+    function isNaN(value) {
+      // `NaN` as a primitive is the only value that is not equal to itself
+      // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+      return isNumber(value) && value != +value;
+    }
+
+    /**
+     * Checks if `value` is `null`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
+     * @example
+     *
+     * _.isNull(null);
+     * // => true
+     *
+     * _.isNull(undefined);
+     * // => false
+     */
+    function isNull(value) {
+      return value === null;
+    }
+
+    /**
+     * Checks if `value` is a number.
+     *
+     * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
+     * @example
+     *
+     * _.isNumber(8.4 * 5);
+     * // => true
+     */
+    function isNumber(value) {
+      return typeof value == 'number' ||
+        value && typeof value == 'object' && toString.call(value) == numberClass || false;
+    }
+
+    /**
+     * Checks if `value` is an object created by the `Object` constructor.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * _.isPlainObject(new Shape);
+     * // => false
+     *
+     * _.isPlainObject([1, 2, 3]);
+     * // => false
+     *
+     * _.isPlainObject({ 'x': 0, 'y': 0 });
+     * // => true
+     */
+    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+      if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) {
+        return false;
+      }
+      var valueOf = value.valueOf,
+          objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+      return objProto
+        ? (value == objProto || getPrototypeOf(value) == objProto)
+        : shimIsPlainObject(value);
+    };
+
+    /**
+     * Checks if `value` is a regular expression.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
+     * @example
+     *
+     * _.isRegExp(/fred/);
+     * // => true
+     */
+    function isRegExp(value) {
+      return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false;
+    }
+
+    /**
+     * Checks if `value` is a string.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
+     * @example
+     *
+     * _.isString('fred');
+     * // => true
+     */
+    function isString(value) {
+      return typeof value == 'string' ||
+        value && typeof value == 'object' && toString.call(value) == stringClass || false;
+    }
+
+    /**
+     * Checks if `value` is `undefined`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
+     * @example
+     *
+     * _.isUndefined(void 0);
+     * // => true
+     */
+    function isUndefined(value) {
+      return typeof value == 'undefined';
+    }
+
+    /**
+     * Creates an object with the same keys as `object` and values generated by
+     * running each own enumerable property of `object` through the callback.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new object with values of the results of each `callback` execution.
+     * @example
+     *
+     * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     *
+     * var characters = {
+     *   'fred': { 'name': 'fred', 'age': 40 },
+     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.mapValues(characters, 'age');
+     * // => { 'fred': 40, 'pebbles': 1 }
+     */
+    function mapValues(object, callback, thisArg) {
+      var result = {};
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      forOwn(object, function(value, key, object) {
+        result[key] = callback(value, key, object);
+      });
+      return result;
+    }
+
+    /**
+     * Recursively merges own enumerable properties of the source object(s), that
+     * don't resolve to `undefined` into the destination object. Subsequent sources
+     * will overwrite property assignments of previous sources. If a callback is
+     * provided it will be executed to produce the merged values of the destination
+     * and source properties. If the callback returns `undefined` merging will
+     * be handled by the method instead. The callback is bound to `thisArg` and
+     * invoked with two arguments; (objectValue, sourceValue).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The destination object.
+     * @param {...Object} [source] The source objects.
+     * @param {Function} [callback] The function to customize merging properties.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the destination object.
+     * @example
+     *
+     * var names = {
+     *   'characters': [
+     *     { 'name': 'barney' },
+     *     { 'name': 'fred' }
+     *   ]
+     * };
+     *
+     * var ages = {
+     *   'characters': [
+     *     { 'age': 36 },
+     *     { 'age': 40 }
+     *   ]
+     * };
+     *
+     * _.merge(names, ages);
+     * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
+     *
+     * var food = {
+     *   'fruits': ['apple'],
+     *   'vegetables': ['beet']
+     * };
+     *
+     * var otherFood = {
+     *   'fruits': ['banana'],
+     *   'vegetables': ['carrot']
+     * };
+     *
+     * _.merge(food, otherFood, function(a, b) {
+     *   return _.isArray(a) ? a.concat(b) : undefined;
+     * });
+     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
+     */
+    function merge(object) {
+      var args = arguments,
+          length = 2;
+
+      if (!isObject(object)) {
+        return object;
+      }
+      // allows working with `_.reduce` and `_.reduceRight` without using
+      // their `index` and `collection` arguments
+      if (typeof args[2] != 'number') {
+        length = args.length;
+      }
+      if (length > 3 && typeof args[length - 2] == 'function') {
+        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
+      } else if (length > 2 && typeof args[length - 1] == 'function') {
+        callback = args[--length];
+      }
+      var sources = slice(arguments, 1, length),
+          index = -1,
+          stackA = getArray(),
+          stackB = getArray();
+
+      while (++index < length) {
+        baseMerge(object, sources[index], callback, stackA, stackB);
+      }
+      releaseArray(stackA);
+      releaseArray(stackB);
+      return object;
+    }
+
+    /**
+     * Creates a shallow clone of `object` excluding the specified properties.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If a callback is provided it will be executed for each
+     * property of `object` omitting the properties the callback returns truey
+     * for. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The source object.
+     * @param {Function|...string|string[]} [callback] The properties to omit or the
+     *  function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns an object without the omitted properties.
+     * @example
+     *
+     * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
+     * // => { 'name': 'fred' }
+     *
+     * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
+     *   return typeof value == 'number';
+     * });
+     * // => { 'name': 'fred' }
+     */
+    function omit(object, callback, thisArg) {
+      var result = {};
+      if (typeof callback != 'function') {
+        var props = [];
+        forIn(object, function(value, key) {
+          props.push(key);
+        });
+        props = baseDifference(props, baseFlatten(arguments, true, false, 1));
+
+        var index = -1,
+            length = props.length;
+
+        while (++index < length) {
+          var key = props[index];
+          result[key] = object[key];
+        }
+      } else {
+        callback = lodash.createCallback(callback, thisArg, 3);
+        forIn(object, function(value, key, object) {
+          if (!callback(value, key, object)) {
+            result[key] = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Creates a two dimensional array of an object's key-value pairs,
+     * i.e. `[[key1, value1], [key2, value2]]`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns new array of key-value pairs.
+     * @example
+     *
+     * _.pairs({ 'barney': 36, 'fred': 40 });
+     * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
+     */
+    function pairs(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        var key = props[index];
+        result[index] = [key, object[key]];
+      }
+      return result;
+    }
+
+    /**
+     * Creates a shallow clone of `object` composed of the specified properties.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If a callback is provided it will be executed for each
+     * property of `object` picking the properties the callback returns truey
+     * for. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The source object.
+     * @param {Function|...string|string[]} [callback] The function called per
+     *  iteration or property names to pick, specified as individual property
+     *  names or arrays of property names.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns an object composed of the picked properties.
+     * @example
+     *
+     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
+     * // => { 'name': 'fred' }
+     *
+     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
+     *   return key.charAt(0) != '_';
+     * });
+     * // => { 'name': 'fred' }
+     */
+    function pick(object, callback, thisArg) {
+      var result = {};
+      if (typeof callback != 'function') {
+        var index = -1,
+            props = baseFlatten(arguments, true, false, 1),
+            length = isObject(object) ? props.length : 0;
+
+        while (++index < length) {
+          var key = props[index];
+          if (key in object) {
+            result[key] = object[key];
+          }
+        }
+      } else {
+        callback = lodash.createCallback(callback, thisArg, 3);
+        forIn(object, function(value, key, object) {
+          if (callback(value, key, object)) {
+            result[key] = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * An alternative to `_.reduce` this method transforms `object` to a new
+     * `accumulator` object which is the result of running each of its own
+     * enumerable properties through a callback, with each callback execution
+     * potentially mutating the `accumulator` object. The callback is bound to
+     * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
+     * Callbacks may exit iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Array|Object} object The object to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] The custom accumulator value.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
+     *   num *= num;
+     *   if (num % 2) {
+     *     return result.push(num) < 3;
+     *   }
+     * });
+     * // => [1, 9, 25]
+     *
+     * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+     *   result[key] = num * 3;
+     * });
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     */
+    function transform(object, callback, accumulator, thisArg) {
+      var isArr = isArray(object);
+      if (accumulator == null) {
+        if (isArr) {
+          accumulator = [];
+        } else {
+          var ctor = object && object.constructor,
+              proto = ctor && ctor.prototype;
+
+          accumulator = baseCreate(proto);
+        }
+      }
+      if (callback) {
+        callback = lodash.createCallback(callback, thisArg, 4);
+        (isArr ? baseEach : forOwn)(object, function(value, index, object) {
+          return callback(accumulator, value, index, object);
+        });
+      }
+      return accumulator;
+    }
+
+    /**
+     * Creates an array composed of the own enumerable property values of `object`.
+     *
+     * @static
+     * @memberOf _
+     * @category Objects
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns an array of property values.
+     * @example
+     *
+     * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => [1, 2, 3] (property order is not guaranteed across environments)
+     */
+    function values(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = object[props[index]];
+      }
+      return result;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array of elements from the specified indexes, or keys, of the
+     * `collection`. Indexes may be specified as individual arguments or as arrays
+     * of indexes.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
+     *   to retrieve, specified as individual indexes or arrays of indexes.
+     * @returns {Array} Returns a new array of elements corresponding to the
+     *  provided indexes.
+     * @example
+     *
+     * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
+     * // => ['a', 'c', 'e']
+     *
+     * _.at(['fred', 'barney', 'pebbles'], 0, 2);
+     * // => ['fred', 'pebbles']
+     */
+    function at(collection) {
+      var args = arguments,
+          index = -1,
+          props = baseFlatten(args, true, false, 1),
+          length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
+          result = Array(length);
+
+      if (support.unindexedChars && isString(collection)) {
+        collection = collection.split('');
+      }
+      while(++index < length) {
+        result[index] = collection[props[index]];
+      }
+      return result;
+    }
+
+    /**
+     * Checks if a given value is present in a collection using strict equality
+     * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
+     * offset from the end of the collection.
+     *
+     * @static
+     * @memberOf _
+     * @alias include
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {*} target The value to check for.
+     * @param {number} [fromIndex=0] The index to search from.
+     * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
+     * @example
+     *
+     * _.contains([1, 2, 3], 1);
+     * // => true
+     *
+     * _.contains([1, 2, 3], 1, 2);
+     * // => false
+     *
+     * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
+     * // => true
+     *
+     * _.contains('pebbles', 'eb');
+     * // => true
+     */
+    function contains(collection, target, fromIndex) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = collection ? collection.length : 0,
+          result = false;
+
+      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+      if (isArray(collection)) {
+        result = indexOf(collection, target, fromIndex) > -1;
+      } else if (typeof length == 'number') {
+        result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
+      } else {
+        baseEach(collection, function(value) {
+          if (++index >= fromIndex) {
+            return !(result = value === target);
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of `collection` through the callback. The corresponding value
+     * of each key is the number of times the key was returned by the callback.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy(['one', 'two', 'three'], 'length');
+     * // => { '3': 2, '5': 1 }
+     */
+    var countBy = createAggregator(function(result, value, key) {
+      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+    });
+
+    /**
+     * Checks if the given callback returns truey value for **all** elements of
+     * a collection. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias all
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if all elements passed the callback check,
+     *  else `false`.
+     * @example
+     *
+     * _.every([true, 1, null, 'yes']);
+     * // => false
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.every(characters, 'age');
+     * // => true
+     *
+     * // using "_.where" callback shorthand
+     * _.every(characters, { 'age': 36 });
+     * // => false
+     */
+    function every(collection, callback, thisArg) {
+      var result = true;
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          if (!(result = !!callback(collection[index], index, collection))) {
+            break;
+          }
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          return (result = !!callback(value, index, collection));
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, returning an array of all elements
+     * the callback returns truey for. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias select
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of elements that passed the callback check.
+     * @example
+     *
+     * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+     * // => [2, 4, 6]
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.filter(characters, 'blocked');
+     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+     *
+     * // using "_.where" callback shorthand
+     * _.filter(characters, { 'age': 36 });
+     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+     */
+    function filter(collection, callback, thisArg) {
+      var result = [];
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (callback(value, index, collection)) {
+            result.push(value);
+          }
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          if (callback(value, index, collection)) {
+            result.push(value);
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, returning the first element that
+     * the callback returns truey for. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias detect, findWhere
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the found element, else `undefined`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': false },
+     *   { 'name': 'fred',    'age': 40, 'blocked': true },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+     * ];
+     *
+     * _.find(characters, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => { 'name': 'barney', 'age': 36, 'blocked': false }
+     *
+     * // using "_.where" callback shorthand
+     * _.find(characters, { 'age': 1 });
+     * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
+     *
+     * // using "_.pluck" callback shorthand
+     * _.find(characters, 'blocked');
+     * // => { 'name': 'fred', 'age': 40, 'blocked': true }
+     */
+    function find(collection, callback, thisArg) {
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (callback(value, index, collection)) {
+            return value;
+          }
+        }
+      } else {
+        var result;
+        baseEach(collection, function(value, index, collection) {
+          if (callback(value, index, collection)) {
+            result = value;
+            return false;
+          }
+        });
+        return result;
+      }
+    }
+
+    /**
+     * This method is like `_.find` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the found element, else `undefined`.
+     * @example
+     *
+     * _.findLast([1, 2, 3, 4], function(num) {
+     *   return num % 2 == 1;
+     * });
+     * // => 3
+     */
+    function findLast(collection, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forEachRight(collection, function(value, index, collection) {
+        if (callback(value, index, collection)) {
+          result = value;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Iterates over elements of a collection, executing the callback for each
+     * element. The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection). Callbacks may exit iteration early by
+     * explicitly returning `false`.
+     *
+     * Note: As with other "Collections" methods, objects with a `length` property
+     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+     * may be used for object iteration.
+     *
+     * @static
+     * @memberOf _
+     * @alias each
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
+     * // => logs each number and returns '1,2,3'
+     *
+     * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+     * // => logs each number and returns the object (property order is not guaranteed across environments)
+     */
+    function forEach(collection, callback, thisArg) {
+      if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          if (callback(collection[index], index, collection) === false) {
+            break;
+          }
+        }
+      } else {
+        baseEach(collection, callback, thisArg);
+      }
+      return collection;
+    }
+
+    /**
+     * This method is like `_.forEach` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias eachRight
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
+     * // => logs each number from right to left and returns '3,2,1'
+     */
+    function forEachRight(collection, callback, thisArg) {
+      var iterable = collection,
+          length = collection ? collection.length : 0;
+
+      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
+      if (isArray(collection)) {
+        while (length--) {
+          if (callback(collection[length], length, collection) === false) {
+            break;
+          }
+        }
+      } else {
+        if (typeof length != 'number') {
+          var props = keys(collection);
+          length = props.length;
+        } else if (support.unindexedChars && isString(collection)) {
+          iterable = collection.split('');
+        }
+        baseEach(collection, function(value, key, collection) {
+          key = props ? props[--length] : --length;
+          return callback(iterable[key], key, collection);
+        });
+      }
+      return collection;
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of a collection through the callback. The corresponding value
+     * of each key is an array of the elements responsible for generating the key.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * // using "_.pluck" callback shorthand
+     * _.groupBy(['one', 'two', 'three'], 'length');
+     * // => { '3': ['one', 'two'], '5': ['three'] }
+     */
+    var groupBy = createAggregator(function(result, value, key) {
+      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+    });
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of the collection through the given callback. The corresponding
+     * value of each key is the last element responsible for generating the key.
+     * The callback is bound to `thisArg` and invoked with three arguments;
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * var keys = [
+     *   { 'dir': 'left', 'code': 97 },
+     *   { 'dir': 'right', 'code': 100 }
+     * ];
+     *
+     * _.indexBy(keys, 'dir');
+     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     */
+    var indexBy = createAggregator(function(result, value, key) {
+      result[key] = value;
+    });
+
+    /**
+     * Invokes the method named by `methodName` on each element in the `collection`
+     * returning an array of the results of each invoked method. Additional arguments
+     * will be provided to each invoked method. If `methodName` is a function it
+     * will be invoked for, and `this` bound to, each element in the `collection`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|string} methodName The name of the method to invoke or
+     *  the function invoked per iteration.
+     * @param {...*} [arg] Arguments to invoke the method with.
+     * @returns {Array} Returns a new array of the results of each invoked method.
+     * @example
+     *
+     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+     * // => [[1, 5, 7], [1, 2, 3]]
+     *
+     * _.invoke([123, 456], String.prototype.split, '');
+     * // => [['1', '2', '3'], ['4', '5', '6']]
+     */
+    function invoke(collection, methodName) {
+      var args = slice(arguments, 2),
+          index = -1,
+          isFunc = typeof methodName == 'function',
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      forEach(collection, function(value) {
+        result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
+      });
+      return result;
+    }
+
+    /**
+     * Creates an array of values by running each element in the collection
+     * through the callback. The callback is bound to `thisArg` and invoked with
+     * three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias collect
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of the results of each `callback` execution.
+     * @example
+     *
+     * _.map([1, 2, 3], function(num) { return num * 3; });
+     * // => [3, 6, 9]
+     *
+     * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+     * // => [3, 6, 9] (property order is not guaranteed across environments)
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.map(characters, 'name');
+     * // => ['barney', 'fred']
+     */
+    function map(collection, callback, thisArg) {
+      var index = -1,
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      if (isArray(collection)) {
+        while (++index < length) {
+          result[index] = callback(collection[index], index, collection);
+        }
+      } else {
+        baseEach(collection, function(value, key, collection) {
+          result[++index] = callback(value, key, collection);
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the maximum value of a collection. If the collection is empty or
+     * falsey `-Infinity` is returned. If a callback is provided it will be executed
+     * for each value in the collection to generate the criterion by which the value
+     * is ranked. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the maximum value.
+     * @example
+     *
+     * _.max([4, 2, 8, 6]);
+     * // => 8
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.max(characters, function(chr) { return chr.age; });
+     * // => { 'name': 'fred', 'age': 40 };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.max(characters, 'age');
+     * // => { 'name': 'fred', 'age': 40 };
+     */
+    function max(collection, callback, thisArg) {
+      var computed = -Infinity,
+          result = computed;
+
+      // allows working with functions like `_.map` without using
+      // their `index` argument as a callback
+      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+        callback = null;
+      }
+      if (callback == null && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (value > result) {
+            result = value;
+          }
+        }
+      } else {
+        callback = (callback == null && isString(collection))
+          ? charAtCallback
+          : lodash.createCallback(callback, thisArg, 3);
+
+        baseEach(collection, function(value, index, collection) {
+          var current = callback(value, index, collection);
+          if (current > computed) {
+            computed = current;
+            result = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the minimum value of a collection. If the collection is empty or
+     * falsey `Infinity` is returned. If a callback is provided it will be executed
+     * for each value in the collection to generate the criterion by which the value
+     * is ranked. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the minimum value.
+     * @example
+     *
+     * _.min([4, 2, 8, 6]);
+     * // => 2
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.min(characters, function(chr) { return chr.age; });
+     * // => { 'name': 'barney', 'age': 36 };
+     *
+     * // using "_.pluck" callback shorthand
+     * _.min(characters, 'age');
+     * // => { 'name': 'barney', 'age': 36 };
+     */
+    function min(collection, callback, thisArg) {
+      var computed = Infinity,
+          result = computed;
+
+      // allows working with functions like `_.map` without using
+      // their `index` argument as a callback
+      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
+        callback = null;
+      }
+      if (callback == null && isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          var value = collection[index];
+          if (value < result) {
+            result = value;
+          }
+        }
+      } else {
+        callback = (callback == null && isString(collection))
+          ? charAtCallback
+          : lodash.createCallback(callback, thisArg, 3);
+
+        baseEach(collection, function(value, index, collection) {
+          var current = callback(value, index, collection);
+          if (current < computed) {
+            computed = current;
+            result = value;
+          }
+        });
+      }
+      return result;
+    }
+
+    /**
+     * Retrieves the value of a specified property from all elements in the collection.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {string} property The name of the property to pluck.
+     * @returns {Array} Returns a new array of property values.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.pluck(characters, 'name');
+     * // => ['barney', 'fred']
+     */
+    var pluck = map;
+
+    /**
+     * Reduces a collection to a value which is the accumulated result of running
+     * each element in the collection through the callback, where each successive
+     * callback execution consumes the return value of the previous execution. If
+     * `accumulator` is not provided the first element of the collection will be
+     * used as the initial `accumulator` value. The callback is bound to `thisArg`
+     * and invoked with four arguments; (accumulator, value, index|key, collection).
+     *
+     * @static
+     * @memberOf _
+     * @alias foldl, inject
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] Initial value of the accumulator.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var sum = _.reduce([1, 2, 3], function(sum, num) {
+     *   return sum + num;
+     * });
+     * // => 6
+     *
+     * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+     *   result[key] = num * 3;
+     *   return result;
+     * }, {});
+     * // => { 'a': 3, 'b': 6, 'c': 9 }
+     */
+    function reduce(collection, callback, accumulator, thisArg) {
+      var noaccum = arguments.length < 3;
+      callback = lodash.createCallback(callback, thisArg, 4);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        if (noaccum) {
+          accumulator = collection[++index];
+        }
+        while (++index < length) {
+          accumulator = callback(accumulator, collection[index], index, collection);
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          accumulator = noaccum
+            ? (noaccum = false, value)
+            : callback(accumulator, value, index, collection)
+        });
+      }
+      return accumulator;
+    }
+
+    /**
+     * This method is like `_.reduce` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias foldr
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [callback=identity] The function called per iteration.
+     * @param {*} [accumulator] Initial value of the accumulator.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var list = [[0, 1], [2, 3], [4, 5]];
+     * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+     * // => [4, 5, 2, 3, 0, 1]
+     */
+    function reduceRight(collection, callback, accumulator, thisArg) {
+      var noaccum = arguments.length < 3;
+      callback = lodash.createCallback(callback, thisArg, 4);
+      forEachRight(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection);
+      });
+      return accumulator;
+    }
+
+    /**
+     * The opposite of `_.filter` this method returns the elements of a
+     * collection that the callback does **not** return truey for.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of elements that failed the callback check.
+     * @example
+     *
+     * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+     * // => [1, 3, 5]
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.reject(characters, 'blocked');
+     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+     *
+     * // using "_.where" callback shorthand
+     * _.reject(characters, { 'age': 36 });
+     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+     */
+    function reject(collection, callback, thisArg) {
+      callback = lodash.createCallback(callback, thisArg, 3);
+      return filter(collection, function(value, index, collection) {
+        return !callback(value, index, collection);
+      });
+    }
+
+    /**
+     * Retrieves a random element or `n` random elements from a collection.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to sample.
+     * @param {number} [n] The number of elements to sample.
+     * @param- {Object} [guard] Allows working with functions like `_.map`
+     *  without using their `index` arguments as `n`.
+     * @returns {Array} Returns the random sample(s) of `collection`.
+     * @example
+     *
+     * _.sample([1, 2, 3, 4]);
+     * // => 2
+     *
+     * _.sample([1, 2, 3, 4], 2);
+     * // => [3, 1]
+     */
+    function sample(collection, n, guard) {
+      if (collection && typeof collection.length != 'number') {
+        collection = values(collection);
+      } else if (support.unindexedChars && isString(collection)) {
+        collection = collection.split('');
+      }
+      if (n == null || guard) {
+        return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
+      }
+      var result = shuffle(collection);
+      result.length = nativeMin(nativeMax(0, n), result.length);
+      return result;
+    }
+
+    /**
+     * Creates an array of shuffled values, using a version of the Fisher-Yates
+     * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to shuffle.
+     * @returns {Array} Returns a new shuffled collection.
+     * @example
+     *
+     * _.shuffle([1, 2, 3, 4, 5, 6]);
+     * // => [4, 1, 6, 3, 5, 2]
+     */
+    function shuffle(collection) {
+      var index = -1,
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      forEach(collection, function(value) {
+        var rand = baseRandom(0, ++index);
+        result[index] = result[rand];
+        result[rand] = value;
+      });
+      return result;
+    }
+
+    /**
+     * Gets the size of the `collection` by returning `collection.length` for arrays
+     * and array-like objects or the number of own enumerable properties for objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to inspect.
+     * @returns {number} Returns `collection.length` or number of own enumerable properties.
+     * @example
+     *
+     * _.size([1, 2]);
+     * // => 2
+     *
+     * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+     * // => 3
+     *
+     * _.size('pebbles');
+     * // => 7
+     */
+    function size(collection) {
+      var length = collection ? collection.length : 0;
+      return typeof length == 'number' ? length : keys(collection).length;
+    }
+
+    /**
+     * Checks if the callback returns a truey value for **any** element of a
+     * collection. The function returns as soon as it finds a passing value and
+     * does not iterate over the entire collection. The callback is bound to
+     * `thisArg` and invoked with three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias any
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {boolean} Returns `true` if any element passed the callback check,
+     *  else `false`.
+     * @example
+     *
+     * _.some([null, 0, 'yes', false], Boolean);
+     * // => true
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'blocked': false },
+     *   { 'name': 'fred',   'age': 40, 'blocked': true }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.some(characters, 'blocked');
+     * // => true
+     *
+     * // using "_.where" callback shorthand
+     * _.some(characters, { 'age': 1 });
+     * // => false
+     */
+    function some(collection, callback, thisArg) {
+      var result;
+      callback = lodash.createCallback(callback, thisArg, 3);
+
+      if (isArray(collection)) {
+        var index = -1,
+            length = collection.length;
+
+        while (++index < length) {
+          if ((result = callback(collection[index], index, collection))) {
+            break;
+          }
+        }
+      } else {
+        baseEach(collection, function(value, index, collection) {
+          return !(result = callback(value, index, collection));
+        });
+      }
+      return !!result;
+    }
+
+    /**
+     * Creates an array of elements, sorted in ascending order by the results of
+     * running each element in a collection through the callback. This method
+     * performs a stable sort, that is, it will preserve the original sort order
+     * of equal elements. The callback is bound to `thisArg` and invoked with
+     * three arguments; (value, index|key, collection).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an array of property names is provided for `callback` the collection
+     * will be sorted by each property value.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Array|Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of sorted elements.
+     * @example
+     *
+     * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+     * // => [3, 1, 2]
+     *
+     * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+     * // => [3, 1, 2]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36 },
+     *   { 'name': 'fred',    'age': 40 },
+     *   { 'name': 'barney',  'age': 26 },
+     *   { 'name': 'fred',    'age': 30 }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.map(_.sortBy(characters, 'age'), _.values);
+     * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
+     *
+     * // sorting by multiple properties
+     * _.map(_.sortBy(characters, ['name', 'age']), _.values);
+     * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
+     */
+    function sortBy(collection, callback, thisArg) {
+      var index = -1,
+          isArr = isArray(callback),
+          length = collection ? collection.length : 0,
+          result = Array(typeof length == 'number' ? length : 0);
+
+      if (!isArr) {
+        callback = lodash.createCallback(callback, thisArg, 3);
+      }
+      forEach(collection, function(value, key, collection) {
+        var object = result[++index] = getObject();
+        if (isArr) {
+          object.criteria = map(callback, function(key) { return value[key]; });
+        } else {
+          (object.criteria = getArray())[0] = callback(value, key, collection);
+        }
+        object.index = index;
+        object.value = value;
+      });
+
+      length = result.length;
+      result.sort(compareAscending);
+      while (length--) {
+        var object = result[length];
+        result[length] = object.value;
+        if (!isArr) {
+          releaseArray(object.criteria);
+        }
+        releaseObject(object);
+      }
+      return result;
+    }
+
+    /**
+     * Converts the `collection` to an array.
+     *
+     * @static
+     * @memberOf _
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to convert.
+     * @returns {Array} Returns the new converted array.
+     * @example
+     *
+     * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+     * // => [2, 3, 4]
+     */
+    function toArray(collection) {
+      if (collection && typeof collection.length == 'number') {
+        return (support.unindexedChars && isString(collection))
+          ? collection.split('')
+          : slice(collection);
+      }
+      return values(collection);
+    }
+
+    /**
+     * Performs a deep comparison of each element in a `collection` to the given
+     * `properties` object, returning an array of all elements that have equivalent
+     * property values.
+     *
+     * @static
+     * @memberOf _
+     * @type Function
+     * @category Collections
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Object} props The object of property values to filter by.
+     * @returns {Array} Returns a new array of elements that have the given properties.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
+     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * _.where(characters, { 'age': 36 });
+     * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
+     *
+     * _.where(characters, { 'pets': ['dino'] });
+     * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
+     */
+    var where = filter;
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array with all falsey values removed. The values `false`, `null`,
+     * `0`, `""`, `undefined`, and `NaN` are all falsey.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to compact.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.compact([0, 1, false, 2, '', 3]);
+     * // => [1, 2, 3]
+     */
+    function compact(array) {
+      var index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+        if (value) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array excluding all values of the provided arrays using strict
+     * equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to process.
+     * @param {...Array} [values] The arrays of values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+     * // => [1, 3, 4]
+     */
+    function difference(array) {
+      return baseDifference(array, baseFlatten(arguments, true, true, 1));
+    }
+
+    /**
+     * This method is like `_.find` except that it returns the index of the first
+     * element that passes the callback check, instead of the element itself.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': false },
+     *   { 'name': 'fred',    'age': 40, 'blocked': true },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
+     * ];
+     *
+     * _.findIndex(characters, function(chr) {
+     *   return chr.age < 20;
+     * });
+     * // => 2
+     *
+     * // using "_.where" callback shorthand
+     * _.findIndex(characters, { 'age': 36 });
+     * // => 0
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findIndex(characters, 'blocked');
+     * // => 1
+     */
+    function findIndex(array, callback, thisArg) {
+      var index = -1,
+          length = array ? array.length : 0;
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (++index < length) {
+        if (callback(array[index], index, array)) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * This method is like `_.findIndex` except that it iterates over elements
+     * of a `collection` from right to left.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36, 'blocked': true },
+     *   { 'name': 'fred',    'age': 40, 'blocked': false },
+     *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
+     * ];
+     *
+     * _.findLastIndex(characters, function(chr) {
+     *   return chr.age > 30;
+     * });
+     * // => 1
+     *
+     * // using "_.where" callback shorthand
+     * _.findLastIndex(characters, { 'age': 36 });
+     * // => 0
+     *
+     * // using "_.pluck" callback shorthand
+     * _.findLastIndex(characters, 'blocked');
+     * // => 2
+     */
+    function findLastIndex(array, callback, thisArg) {
+      var length = array ? array.length : 0;
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (length--) {
+        if (callback(array[length], length, array)) {
+          return length;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Gets the first element or first `n` elements of an array. If a callback
+     * is provided elements at the beginning of the array are returned as long
+     * as the callback returns truey. The callback is bound to `thisArg` and
+     * invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias head, take
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback] The function called
+     *  per element or the number of elements to return. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the first element(s) of `array`.
+     * @example
+     *
+     * _.first([1, 2, 3]);
+     * // => 1
+     *
+     * _.first([1, 2, 3], 2);
+     * // => [1, 2]
+     *
+     * _.first([1, 2, 3], function(num) {
+     *   return num < 3;
+     * });
+     * // => [1, 2]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.first(characters, 'blocked');
+     * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
+     *
+     * // using "_.where" callback shorthand
+     * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
+     * // => ['barney', 'fred']
+     */
+    function first(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = -1;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array ? array[0] : undefined;
+        }
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, n), length));
+    }
+
+    /**
+     * Flattens a nested array (the nesting can be to any depth). If `isShallow`
+     * is truey, the array will only be flattened a single level. If a callback
+     * is provided each element of the array is passed through the callback before
+     * flattening. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new flattened array.
+     * @example
+     *
+     * _.flatten([1, [2], [3, [[4]]]]);
+     * // => [1, 2, 3, 4];
+     *
+     * _.flatten([1, [2], [3, [[4]]]], true);
+     * // => [1, 2, 3, [[4]]];
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
+     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.flatten(characters, 'pets');
+     * // => ['hoppy', 'baby puss', 'dino']
+     */
+    function flatten(array, isShallow, callback, thisArg) {
+      // juggle arguments
+      if (typeof isShallow != 'boolean' && isShallow != null) {
+        thisArg = callback;
+        callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
+        isShallow = false;
+      }
+      if (callback != null) {
+        array = map(array, callback, thisArg);
+      }
+      return baseFlatten(array, isShallow);
+    }
+
+    /**
+     * Gets the index at which the first occurrence of `value` is found using
+     * strict equality for comparisons, i.e. `===`. If the array is already sorted
+     * providing `true` for `fromIndex` will run a faster binary search.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+     *  to perform a binary search on a sorted array.
+     * @returns {number} Returns the index of the matched value or `-1`.
+     * @example
+     *
+     * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+     * // => 1
+     *
+     * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+     * // => 4
+     *
+     * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+     * // => 2
+     */
+    function indexOf(array, value, fromIndex) {
+      if (typeof fromIndex == 'number') {
+        var length = array ? array.length : 0;
+        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
+      } else if (fromIndex) {
+        var index = sortedIndex(array, value);
+        return array[index] === value ? index : -1;
+      }
+      return baseIndexOf(array, value, fromIndex);
+    }
+
+    /**
+     * Gets all but the last element or last `n` elements of an array. If a
+     * callback is provided elements at the end of the array are excluded from
+     * the result as long as the callback returns truey. The callback is bound
+     * to `thisArg` and invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback=1] The function called
+     *  per element or the number of elements to exclude. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a slice of `array`.
+     * @example
+     *
+     * _.initial([1, 2, 3]);
+     * // => [1, 2]
+     *
+     * _.initial([1, 2, 3], 2);
+     * // => [1]
+     *
+     * _.initial([1, 2, 3], function(num) {
+     *   return num > 1;
+     * });
+     * // => [1]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.initial(characters, 'blocked');
+     * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
+     *
+     * // using "_.where" callback shorthand
+     * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
+     * // => ['barney', 'fred']
+     */
+    function initial(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = (callback == null || thisArg) ? 1 : callback || n;
+      }
+      return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+    }
+
+    /**
+     * Creates an array of unique values present in all provided arrays using
+     * strict equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of shared values.
+     * @example
+     *
+     * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+     * // => [1, 2]
+     */
+    function intersection() {
+      var args = [],
+          argsIndex = -1,
+          argsLength = arguments.length,
+          caches = getArray(),
+          indexOf = getIndexOf(),
+          trustIndexOf = indexOf === baseIndexOf,
+          seen = getArray();
+
+      while (++argsIndex < argsLength) {
+        var value = arguments[argsIndex];
+        if (isArray(value) || isArguments(value)) {
+          args.push(value);
+          caches.push(trustIndexOf && value.length >= largeArraySize &&
+            createCache(argsIndex ? args[argsIndex] : seen));
+        }
+      }
+      var array = args[0],
+          index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      outer:
+      while (++index < length) {
+        var cache = caches[0];
+        value = array[index];
+
+        if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
+          argsIndex = argsLength;
+          (cache || seen).push(value);
+          while (--argsIndex) {
+            cache = caches[argsIndex];
+            if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
+              continue outer;
+            }
+          }
+          result.push(value);
+        }
+      }
+      while (argsLength--) {
+        cache = caches[argsLength];
+        if (cache) {
+          releaseObject(cache);
+        }
+      }
+      releaseArray(caches);
+      releaseArray(seen);
+      return result;
+    }
+
+    /**
+     * Gets the last element or last `n` elements of an array. If a callback is
+     * provided elements at the end of the array are returned as long as the
+     * callback returns truey. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback] The function called
+     *  per element or the number of elements to return. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {*} Returns the last element(s) of `array`.
+     * @example
+     *
+     * _.last([1, 2, 3]);
+     * // => 3
+     *
+     * _.last([1, 2, 3], 2);
+     * // => [2, 3]
+     *
+     * _.last([1, 2, 3], function(num) {
+     *   return num > 1;
+     * });
+     * // => [2, 3]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.pluck(_.last(characters, 'blocked'), 'name');
+     * // => ['fred', 'pebbles']
+     *
+     * // using "_.where" callback shorthand
+     * _.last(characters, { 'employer': 'na' });
+     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+     */
+    function last(array, callback, thisArg) {
+      var n = 0,
+          length = array ? array.length : 0;
+
+      if (typeof callback != 'number' && callback != null) {
+        var index = length;
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (index-- && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = callback;
+        if (n == null || thisArg) {
+          return array ? array[length - 1] : undefined;
+        }
+      }
+      return slice(array, nativeMax(0, length - n));
+    }
+
+    /**
+     * Gets the index at which the last occurrence of `value` is found using strict
+     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+     * as the offset from the end of the collection.
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {number} [fromIndex=array.length-1] The index to search from.
+     * @returns {number} Returns the index of the matched value or `-1`.
+     * @example
+     *
+     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+     * // => 4
+     *
+     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+     * // => 1
+     */
+    function lastIndexOf(array, value, fromIndex) {
+      var index = array ? array.length : 0;
+      if (typeof fromIndex == 'number') {
+        index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+      }
+      while (index--) {
+        if (array[index] === value) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Removes all provided values from the given array using strict equality for
+     * comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to modify.
+     * @param {...*} [value] The values to remove.
+     * @returns {Array} Returns `array`.
+     * @example
+     *
+     * var array = [1, 2, 3, 1, 2, 3];
+     * _.pull(array, 2, 3);
+     * console.log(array);
+     * // => [1, 1]
+     */
+    function pull(array) {
+      var args = arguments,
+          argsIndex = 0,
+          argsLength = args.length,
+          length = array ? array.length : 0;
+
+      while (++argsIndex < argsLength) {
+        var index = -1,
+            value = args[argsIndex];
+        while (++index < length) {
+          if (array[index] === value) {
+            splice.call(array, index--, 1);
+            length--;
+          }
+        }
+      }
+      return array;
+    }
+
+    /**
+     * Creates an array of numbers (positive and/or negative) progressing from
+     * `start` up to but not including `end`. If `start` is less than `stop` a
+     * zero-length range is created unless a negative `step` is specified.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {number} [start=0] The start of the range.
+     * @param {number} end The end of the range.
+     * @param {number} [step=1] The value to increment or decrement by.
+     * @returns {Array} Returns a new range array.
+     * @example
+     *
+     * _.range(4);
+     * // => [0, 1, 2, 3]
+     *
+     * _.range(1, 5);
+     * // => [1, 2, 3, 4]
+     *
+     * _.range(0, 20, 5);
+     * // => [0, 5, 10, 15]
+     *
+     * _.range(0, -4, -1);
+     * // => [0, -1, -2, -3]
+     *
+     * _.range(1, 4, 0);
+     * // => [1, 1, 1]
+     *
+     * _.range(0);
+     * // => []
+     */
+    function range(start, end, step) {
+      start = +start || 0;
+      step = typeof step == 'number' ? step : (+step || 1);
+
+      if (end == null) {
+        end = start;
+        start = 0;
+      }
+      // use `Array(length)` so engines like Chakra and V8 avoid slower modes
+      // http://youtu.be/XAqIpGU8ZZk#t=17m25s
+      var index = -1,
+          length = nativeMax(0, ceil((end - start) / (step || 1))),
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = start;
+        start += step;
+      }
+      return result;
+    }
+
+    /**
+     * Removes all elements from an array that the callback returns truey for
+     * and returns an array of removed elements. The callback is bound to `thisArg`
+     * and invoked with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to modify.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a new array of removed elements.
+     * @example
+     *
+     * var array = [1, 2, 3, 4, 5, 6];
+     * var evens = _.remove(array, function(num) { return num % 2 == 0; });
+     *
+     * console.log(array);
+     * // => [1, 3, 5]
+     *
+     * console.log(evens);
+     * // => [2, 4, 6]
+     */
+    function remove(array, callback, thisArg) {
+      var index = -1,
+          length = array ? array.length : 0,
+          result = [];
+
+      callback = lodash.createCallback(callback, thisArg, 3);
+      while (++index < length) {
+        var value = array[index];
+        if (callback(value, index, array)) {
+          result.push(value);
+          splice.call(array, index--, 1);
+          length--;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The opposite of `_.initial` this method gets all but the first element or
+     * first `n` elements of an array. If a callback function is provided elements
+     * at the beginning of the array are excluded from the result as long as the
+     * callback returns truey. The callback is bound to `thisArg` and invoked
+     * with three arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias drop, tail
+     * @category Arrays
+     * @param {Array} array The array to query.
+     * @param {Function|Object|number|string} [callback=1] The function called
+     *  per element or the number of elements to exclude. If a property name or
+     *  object is provided it will be used to create a "_.pluck" or "_.where"
+     *  style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a slice of `array`.
+     * @example
+     *
+     * _.rest([1, 2, 3]);
+     * // => [2, 3]
+     *
+     * _.rest([1, 2, 3], 2);
+     * // => [3]
+     *
+     * _.rest([1, 2, 3], function(num) {
+     *   return num < 3;
+     * });
+     * // => [3]
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
+     *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
+     *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
+     * ];
+     *
+     * // using "_.pluck" callback shorthand
+     * _.pluck(_.rest(characters, 'blocked'), 'name');
+     * // => ['fred', 'pebbles']
+     *
+     * // using "_.where" callback shorthand
+     * _.rest(characters, { 'employer': 'slate' });
+     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
+     */
+    function rest(array, callback, thisArg) {
+      if (typeof callback != 'number' && callback != null) {
+        var n = 0,
+            index = -1,
+            length = array ? array.length : 0;
+
+        callback = lodash.createCallback(callback, thisArg, 3);
+        while (++index < length && callback(array[index], index, array)) {
+          n++;
+        }
+      } else {
+        n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
+      }
+      return slice(array, n);
+    }
+
+    /**
+     * Uses a binary search to determine the smallest index at which a value
+     * should be inserted into a given sorted array in order to maintain the sort
+     * order of the array. If a callback is provided it will be executed for
+     * `value` and each element of `array` to compute their sort ranking. The
+     * callback is bound to `thisArg` and invoked with one argument; (value).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     * @example
+     *
+     * _.sortedIndex([20, 30, 50], 40);
+     * // => 2
+     *
+     * // using "_.pluck" callback shorthand
+     * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+     * // => 2
+     *
+     * var dict = {
+     *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+     * };
+     *
+     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+     *   return dict.wordToNumber[word];
+     * });
+     * // => 2
+     *
+     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+     *   return this.wordToNumber[word];
+     * }, dict);
+     * // => 2
+     */
+    function sortedIndex(array, value, callback, thisArg) {
+      var low = 0,
+          high = array ? array.length : low;
+
+      // explicitly reference `identity` for better inlining in Firefox
+      callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
+      value = callback(value);
+
+      while (low < high) {
+        var mid = (low + high) >>> 1;
+        (callback(array[mid]) < value)
+          ? low = mid + 1
+          : high = mid;
+      }
+      return low;
+    }
+
+    /**
+     * Creates an array of unique values, in order, of the provided arrays using
+     * strict equality for comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of combined values.
+     * @example
+     *
+     * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
+     * // => [1, 2, 3, 5, 4]
+     */
+    function union() {
+      return baseUniq(baseFlatten(arguments, true, true));
+    }
+
+    /**
+     * Creates a duplicate-value-free version of an array using strict equality
+     * for comparisons, i.e. `===`. If the array is sorted, providing
+     * `true` for `isSorted` will use a faster algorithm. If a callback is provided
+     * each element of `array` is passed through the callback before uniqueness
+     * is computed. The callback is bound to `thisArg` and invoked with three
+     * arguments; (value, index, array).
+     *
+     * If a property name is provided for `callback` the created "_.pluck" style
+     * callback will return the property value of the given element.
+     *
+     * If an object is provided for `callback` the created "_.where" style callback
+     * will return `true` for elements that have the properties of the given object,
+     * else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias unique
+     * @category Arrays
+     * @param {Array} array The array to process.
+     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+     * @param {Function|Object|string} [callback=identity] The function called
+     *  per iteration. If a property name or object is provided it will be used
+     *  to create a "_.pluck" or "_.where" style callback, respectively.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns a duplicate-value-free array.
+     * @example
+     *
+     * _.uniq([1, 2, 1, 3, 1]);
+     * // => [1, 2, 3]
+     *
+     * _.uniq([1, 1, 2, 2, 3], true);
+     * // => [1, 2, 3]
+     *
+     * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
+     * // => ['A', 'b', 'C']
+     *
+     * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+     * // => [1, 2.5, 3]
+     *
+     * // using "_.pluck" callback shorthand
+     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+     * // => [{ 'x': 1 }, { 'x': 2 }]
+     */
+    function uniq(array, isSorted, callback, thisArg) {
+      // juggle arguments
+      if (typeof isSorted != 'boolean' && isSorted != null) {
+        thisArg = callback;
+        callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
+        isSorted = false;
+      }
+      if (callback != null) {
+        callback = lodash.createCallback(callback, thisArg, 3);
+      }
+      return baseUniq(array, isSorted, callback);
+    }
+
+    /**
+     * Creates an array excluding all provided values using strict equality for
+     * comparisons, i.e. `===`.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {Array} array The array to filter.
+     * @param {...*} [value] The values to exclude.
+     * @returns {Array} Returns a new array of filtered values.
+     * @example
+     *
+     * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+     * // => [2, 3, 4]
+     */
+    function without(array) {
+      return baseDifference(array, slice(arguments, 1));
+    }
+
+    /**
+     * Creates an array that is the symmetric difference of the provided arrays.
+     * See http://en.wikipedia.org/wiki/Symmetric_difference.
+     *
+     * @static
+     * @memberOf _
+     * @category Arrays
+     * @param {...Array} [array] The arrays to inspect.
+     * @returns {Array} Returns an array of values.
+     * @example
+     *
+     * _.xor([1, 2, 3], [5, 2, 1, 4]);
+     * // => [3, 5, 4]
+     *
+     * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
+     * // => [1, 4, 5]
+     */
+    function xor() {
+      var index = -1,
+          length = arguments.length;
+
+      while (++index < length) {
+        var array = arguments[index];
+        if (isArray(array) || isArguments(array)) {
+          var result = result
+            ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
+            : array;
+        }
+      }
+      return result || [];
+    }
+
+    /**
+     * Creates an array of grouped elements, the first of which contains the first
+     * elements of the given arrays, the second of which contains the second
+     * elements of the given arrays, and so on.
+     *
+     * @static
+     * @memberOf _
+     * @alias unzip
+     * @category Arrays
+     * @param {...Array} [array] Arrays to process.
+     * @returns {Array} Returns a new array of grouped elements.
+     * @example
+     *
+     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+     * // => [['fred', 30, true], ['barney', 40, false]]
+     */
+    function zip() {
+      var array = arguments.length > 1 ? arguments : arguments[0],
+          index = -1,
+          length = array ? max(pluck(array, 'length')) : 0,
+          result = Array(length < 0 ? 0 : length);
+
+      while (++index < length) {
+        result[index] = pluck(array, index);
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed from arrays of `keys` and `values`. Provide
+     * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
+     * or two arrays, one of `keys` and one of corresponding `values`.
+     *
+     * @static
+     * @memberOf _
+     * @alias object
+     * @category Arrays
+     * @param {Array} keys The array of keys.
+     * @param {Array} [values=[]] The array of values.
+     * @returns {Object} Returns an object composed of the given keys and
+     *  corresponding values.
+     * @example
+     *
+     * _.zipObject(['fred', 'barney'], [30, 40]);
+     * // => { 'fred': 30, 'barney': 40 }
+     */
+    function zipObject(keys, values) {
+      var index = -1,
+          length = keys ? keys.length : 0,
+          result = {};
+
+      if (!values && length && !isArray(keys[0])) {
+        values = [];
+      }
+      while (++index < length) {
+        var key = keys[index];
+        if (values) {
+          result[key] = values[index];
+        } else if (key) {
+          result[key[0]] = key[1];
+        }
+      }
+      return result;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a function that executes `func`, with  the `this` binding and
+     * arguments of the created function, only after being called `n` times.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {number} n The number of times the function must be called before
+     *  `func` is executed.
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var saves = ['profile', 'settings'];
+     *
+     * var done = _.after(saves.length, function() {
+     *   console.log('Done saving!');
+     * });
+     *
+     * _.forEach(saves, function(type) {
+     *   asyncSave({ 'type': type, 'complete': done });
+     * });
+     * // => logs 'Done saving!', after all saves have completed
+     */
+    function after(n, func) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      return function() {
+        if (--n < 1) {
+          return func.apply(this, arguments);
+        }
+      };
+    }
+
+    /**
+     * Creates a function that, when called, invokes `func` with the `this`
+     * binding of `thisArg` and prepends any additional `bind` arguments to those
+     * provided to the bound function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to bind.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var func = function(greeting) {
+     *   return greeting + ' ' + this.name;
+     * };
+     *
+     * func = _.bind(func, { 'name': 'fred' }, 'hi');
+     * func();
+     * // => 'hi fred'
+     */
+    function bind(func, thisArg) {
+      return arguments.length > 2
+        ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
+        : createWrapper(func, 1, null, null, thisArg);
+    }
+
+    /**
+     * Binds methods of an object to the object itself, overwriting the existing
+     * method. Method names may be specified as individual arguments or as arrays
+     * of method names. If no method names are provided all the function properties
+     * of `object` will be bound.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Object} object The object to bind and assign the bound methods to.
+     * @param {...string} [methodName] The object method names to
+     *  bind, specified as individual method names or arrays of method names.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'onClick': function() { console.log('clicked ' + this.label); }
+     * };
+     *
+     * _.bindAll(view);
+     * jQuery('#docs').on('click', view.onClick);
+     * // => logs 'clicked docs', when the button is clicked
+     */
+    function bindAll(object) {
+      var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
+          index = -1,
+          length = funcs.length;
+
+      while (++index < length) {
+        var key = funcs[index];
+        object[key] = createWrapper(object[key], 1, null, null, object);
+      }
+      return object;
+    }
+
+    /**
+     * Creates a function that, when called, invokes the method at `object[key]`
+     * and prepends any additional `bindKey` arguments to those provided to the bound
+     * function. This method differs from `_.bind` by allowing bound functions to
+     * reference methods that will be redefined or don't yet exist.
+     * See http://michaux.ca/articles/lazy-function-definition-pattern.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Object} object The object the method belongs to.
+     * @param {string} key The key of the method.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var object = {
+     *   'name': 'fred',
+     *   'greet': function(greeting) {
+     *     return greeting + ' ' + this.name;
+     *   }
+     * };
+     *
+     * var func = _.bindKey(object, 'greet', 'hi');
+     * func();
+     * // => 'hi fred'
+     *
+     * object.greet = function(greeting) {
+     *   return greeting + 'ya ' + this.name + '!';
+     * };
+     *
+     * func();
+     * // => 'hiya fred!'
+     */
+    function bindKey(object, key) {
+      return arguments.length > 2
+        ? createWrapper(key, 19, slice(arguments, 2), null, object)
+        : createWrapper(key, 3, null, null, object);
+    }
+
+    /**
+     * Creates a function that is the composition of the provided functions,
+     * where each function consumes the return value of the function that follows.
+     * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+     * Each function is executed with the `this` binding of the composed function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {...Function} [func] Functions to compose.
+     * @returns {Function} Returns the new composed function.
+     * @example
+     *
+     * var realNameMap = {
+     *   'pebbles': 'penelope'
+     * };
+     *
+     * var format = function(name) {
+     *   name = realNameMap[name.toLowerCase()] || name;
+     *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
+     * };
+     *
+     * var greet = function(formatted) {
+     *   return 'Hiya ' + formatted + '!';
+     * };
+     *
+     * var welcome = _.compose(greet, format);
+     * welcome('pebbles');
+     * // => 'Hiya Penelope!'
+     */
+    function compose() {
+      var funcs = arguments,
+          length = funcs.length;
+
+      while (length--) {
+        if (!isFunction(funcs[length])) {
+          throw new TypeError;
+        }
+      }
+      return function() {
+        var args = arguments,
+            length = funcs.length;
+
+        while (length--) {
+          args = [funcs[length].apply(this, args)];
+        }
+        return args[0];
+      };
+    }
+
+    /**
+     * Creates a function which accepts one or more arguments of `func` that when
+     * invoked either executes `func` returning its result, if all `func` arguments
+     * have been provided, or returns a function that accepts one or more of the
+     * remaining `func` arguments, and so on. The arity of `func` can be specified
+     * if `func.length` is not sufficient.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to curry.
+     * @param {number} [arity=func.length] The arity of `func`.
+     * @returns {Function} Returns the new curried function.
+     * @example
+     *
+     * var curried = _.curry(function(a, b, c) {
+     *   console.log(a + b + c);
+     * });
+     *
+     * curried(1)(2)(3);
+     * // => 6
+     *
+     * curried(1, 2)(3);
+     * // => 6
+     *
+     * curried(1, 2, 3);
+     * // => 6
+     */
+    function curry(func, arity) {
+      arity = typeof arity == 'number' ? arity : (+arity || func.length);
+      return createWrapper(func, 4, null, null, null, arity);
+    }
+
+    /**
+     * Creates a function that will delay the execution of `func` until after
+     * `wait` milliseconds have elapsed since the last time it was invoked.
+     * Provide an options object to indicate that `func` should be invoked on
+     * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
+     * to the debounced function will return the result of the last `func` call.
+     *
+     * Note: If `leading` and `trailing` options are `true` `func` will be called
+     * on the trailing edge of the timeout only if the the debounced function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to debounce.
+     * @param {number} wait The number of milliseconds to delay.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
+     * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
+     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+     * @returns {Function} Returns the new debounced function.
+     * @example
+     *
+     * // avoid costly calculations while the window size is in flux
+     * var lazyLayout = _.debounce(calculateLayout, 150);
+     * jQuery(window).on('resize', lazyLayout);
+     *
+     * // execute `sendMail` when the click event is fired, debouncing subsequent calls
+     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+     *   'leading': true,
+     *   'trailing': false
+     * });
+     *
+     * // ensure `batchLog` is executed once after 1 second of debounced calls
+     * var source = new EventSource('/stream');
+     * source.addEventListener('message', _.debounce(batchLog, 250, {
+     *   'maxWait': 1000
+     * }, false);
+     */
+    function debounce(func, wait, options) {
+      var args,
+          maxTimeoutId,
+          result,
+          stamp,
+          thisArg,
+          timeoutId,
+          trailingCall,
+          lastCalled = 0,
+          maxWait = false,
+          trailing = true;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      wait = nativeMax(0, wait) || 0;
+      if (options === true) {
+        var leading = true;
+        trailing = false;
+      } else if (isObject(options)) {
+        leading = options.leading;
+        maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+      var delayed = function() {
+        var remaining = wait - (now() - stamp);
+        if (remaining <= 0) {
+          if (maxTimeoutId) {
+            clearTimeout(maxTimeoutId);
+          }
+          var isCalled = trailingCall;
+          maxTimeoutId = timeoutId = trailingCall = undefined;
+          if (isCalled) {
+            lastCalled = now();
+            result = func.apply(thisArg, args);
+            if (!timeoutId && !maxTimeoutId) {
+              args = thisArg = null;
+            }
+          }
+        } else {
+          timeoutId = setTimeout(delayed, remaining);
+        }
+      };
+
+      var maxDelayed = function() {
+        if (timeoutId) {
+          clearTimeout(timeoutId);
+        }
+        maxTimeoutId = timeoutId = trailingCall = undefined;
+        if (trailing || (maxWait !== wait)) {
+          lastCalled = now();
+          result = func.apply(thisArg, args);
+          if (!timeoutId && !maxTimeoutId) {
+            args = thisArg = null;
+          }
+        }
+      };
+
+      return function() {
+        args = arguments;
+        stamp = now();
+        thisArg = this;
+        trailingCall = trailing && (timeoutId || !leading);
+
+        if (maxWait === false) {
+          var leadingCall = leading && !timeoutId;
+        } else {
+          if (!maxTimeoutId && !leading) {
+            lastCalled = stamp;
+          }
+          var remaining = maxWait - (stamp - lastCalled),
+              isCalled = remaining <= 0;
+
+          if (isCalled) {
+            if (maxTimeoutId) {
+              maxTimeoutId = clearTimeout(maxTimeoutId);
+            }
+            lastCalled = stamp;
+            result = func.apply(thisArg, args);
+          }
+          else if (!maxTimeoutId) {
+            maxTimeoutId = setTimeout(maxDelayed, remaining);
+          }
+        }
+        if (isCalled && timeoutId) {
+          timeoutId = clearTimeout(timeoutId);
+        }
+        else if (!timeoutId && wait !== maxWait) {
+          timeoutId = setTimeout(delayed, wait);
+        }
+        if (leadingCall) {
+          isCalled = true;
+          result = func.apply(thisArg, args);
+        }
+        if (isCalled && !timeoutId && !maxTimeoutId) {
+          args = thisArg = null;
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Defers executing the `func` function until the current call stack has cleared.
+     * Additional arguments will be provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to defer.
+     * @param {...*} [arg] Arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.defer(function(text) { console.log(text); }, 'deferred');
+     * // logs 'deferred' after one or more milliseconds
+     */
+    function defer(func) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var args = slice(arguments, 1);
+      return setTimeout(function() { func.apply(undefined, args); }, 1);
+    }
+
+    /**
+     * Executes the `func` function after `wait` milliseconds. Additional arguments
+     * will be provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to delay.
+     * @param {number} wait The number of milliseconds to delay execution.
+     * @param {...*} [arg] Arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.delay(function(text) { console.log(text); }, 1000, 'later');
+     * // => logs 'later' after one second
+     */
+    function delay(func, wait) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var args = slice(arguments, 2);
+      return setTimeout(function() { func.apply(undefined, args); }, wait);
+    }
+
+    /**
+     * Creates a function that memoizes the result of `func`. If `resolver` is
+     * provided it will be used to determine the cache key for storing the result
+     * based on the arguments provided to the memoized function. By default, the
+     * first argument provided to the memoized function is used as the cache key.
+     * The `func` is executed with the `this` binding of the memoized function.
+     * The result cache is exposed as the `cache` property on the memoized function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to have its output memoized.
+     * @param {Function} [resolver] A function used to resolve the cache key.
+     * @returns {Function} Returns the new memoizing function.
+     * @example
+     *
+     * var fibonacci = _.memoize(function(n) {
+     *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+     * });
+     *
+     * fibonacci(9)
+     * // => 34
+     *
+     * var data = {
+     *   'fred': { 'name': 'fred', 'age': 40 },
+     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // modifying the result cache
+     * var get = _.memoize(function(name) { return data[name]; }, _.identity);
+     * get('pebbles');
+     * // => { 'name': 'pebbles', 'age': 1 }
+     *
+     * get.cache.pebbles.name = 'penelope';
+     * get('pebbles');
+     * // => { 'name': 'penelope', 'age': 1 }
+     */
+    function memoize(func, resolver) {
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      var memoized = function() {
+        var cache = memoized.cache,
+            key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
+
+        return hasOwnProperty.call(cache, key)
+          ? cache[key]
+          : (cache[key] = func.apply(this, arguments));
+      }
+      memoized.cache = {};
+      return memoized;
+    }
+
+    /**
+     * Creates a function that is restricted to execute `func` once. Repeat calls to
+     * the function will return the value of the first call. The `func` is executed
+     * with the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var initialize = _.once(createApplication);
+     * initialize();
+     * initialize();
+     * // `initialize` executes `createApplication` once
+     */
+    function once(func) {
+      var ran,
+          result;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      return function() {
+        if (ran) {
+          return result;
+        }
+        ran = true;
+        result = func.apply(this, arguments);
+
+        // clear the `func` variable so the function may be garbage collected
+        func = null;
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that, when called, invokes `func` with any additional
+     * `partial` arguments prepended to those provided to the new function. This
+     * method is similar to `_.bind` except it does **not** alter the `this` binding.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var greet = function(greeting, name) { return greeting + ' ' + name; };
+     * var hi = _.partial(greet, 'hi');
+     * hi('fred');
+     * // => 'hi fred'
+     */
+    function partial(func) {
+      return createWrapper(func, 16, slice(arguments, 1));
+    }
+
+    /**
+     * This method is like `_.partial` except that `partial` arguments are
+     * appended to those provided to the new function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [arg] Arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var defaultsDeep = _.partialRight(_.merge, _.defaults);
+     *
+     * var options = {
+     *   'variable': 'data',
+     *   'imports': { 'jq': $ }
+     * };
+     *
+     * defaultsDeep(options, _.templateSettings);
+     *
+     * options.variable
+     * // => 'data'
+     *
+     * options.imports
+     * // => { '_': _, 'jq': $ }
+     */
+    function partialRight(func) {
+      return createWrapper(func, 32, null, slice(arguments, 1));
+    }
+
+    /**
+     * Creates a function that, when executed, will only call the `func` function
+     * at most once per every `wait` milliseconds. Provide an options object to
+     * indicate that `func` should be invoked on the leading and/or trailing edge
+     * of the `wait` timeout. Subsequent calls to the throttled function will
+     * return the result of the last `func` call.
+     *
+     * Note: If `leading` and `trailing` options are `true` `func` will be called
+     * on the trailing edge of the timeout only if the the throttled function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {Function} func The function to throttle.
+     * @param {number} wait The number of milliseconds to throttle executions to.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
+     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
+     * @returns {Function} Returns the new throttled function.
+     * @example
+     *
+     * // avoid excessively updating the position while scrolling
+     * var throttled = _.throttle(updatePosition, 100);
+     * jQuery(window).on('scroll', throttled);
+     *
+     * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
+     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+     *   'trailing': false
+     * }));
+     */
+    function throttle(func, wait, options) {
+      var leading = true,
+          trailing = true;
+
+      if (!isFunction(func)) {
+        throw new TypeError;
+      }
+      if (options === false) {
+        leading = false;
+      } else if (isObject(options)) {
+        leading = 'leading' in options ? options.leading : leading;
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+      debounceOptions.leading = leading;
+      debounceOptions.maxWait = wait;
+      debounceOptions.trailing = trailing;
+
+      return debounce(func, wait, debounceOptions);
+    }
+
+    /**
+     * Creates a function that provides `value` to the wrapper function as its
+     * first argument. Additional arguments provided to the function are appended
+     * to those provided to the wrapper function. The wrapper is executed with
+     * the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Functions
+     * @param {*} value The value to wrap.
+     * @param {Function} wrapper The wrapper function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var p = _.wrap(_.escape, function(func, text) {
+     *   return '<p>' + func(text) + '</p>';
+     * });
+     *
+     * p('Fred, Wilma, & Pebbles');
+     * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
+     */
+    function wrap(value, wrapper) {
+      return createWrapper(wrapper, 16, [value]);
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a function that returns `value`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} value The value to return from the new function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * var getter = _.constant(object);
+     * getter() === object;
+     * // => true
+     */
+    function constant(value) {
+      return function() {
+        return value;
+      };
+    }
+
+    /**
+     * Produces a callback bound to an optional `thisArg`. If `func` is a property
+     * name the created callback will return the property value for a given element.
+     * If `func` is an object the created callback will return `true` for elements
+     * that contain the equivalent object properties, otherwise it will return `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} [func=identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of the created callback.
+     * @param {number} [argCount] The number of arguments the callback accepts.
+     * @returns {Function} Returns a callback function.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // wrap to create custom callback shorthands
+     * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
+     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
+     *   return !match ? func(callback, thisArg) : function(object) {
+     *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
+     *   };
+     * });
+     *
+     * _.filter(characters, 'age__gt38');
+     * // => [{ 'name': 'fred', 'age': 40 }]
+     */
+    function createCallback(func, thisArg, argCount) {
+      var type = typeof func;
+      if (func == null || type == 'function') {
+        return baseCreateCallback(func, thisArg, argCount);
+      }
+      // handle "_.pluck" style callback shorthands
+      if (type != 'object') {
+        return property(func);
+      }
+      var props = keys(func),
+          key = props[0],
+          a = func[key];
+
+      // handle "_.where" style callback shorthands
+      if (props.length == 1 && a === a && !isObject(a)) {
+        // fast path the common case of providing an object with a single
+        // property containing a primitive value
+        return function(object) {
+          var b = object[key];
+          return a === b && (a !== 0 || (1 / a == 1 / b));
+        };
+      }
+      return function(object) {
+        var length = props.length,
+            result = false;
+
+        while (length--) {
+          if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
+            break;
+          }
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+     * corresponding HTML entities.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} string The string to escape.
+     * @returns {string} Returns the escaped string.
+     * @example
+     *
+     * _.escape('Fred, Wilma, & Pebbles');
+     * // => 'Fred, Wilma, &amp; Pebbles'
+     */
+    function escape(string) {
+      return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
+    }
+
+    /**
+     * This method returns the first argument provided to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {*} value Any value.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * _.identity(object) === object;
+     * // => true
+     */
+    function identity(value) {
+      return value;
+    }
+
+    /**
+     * Adds function properties of a source object to the destination object.
+     * If `object` is a function methods will be added to its prototype as well.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {Function|Object} [object=lodash] object The destination object.
+     * @param {Object} source The object of functions to add.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
+     * @example
+     *
+     * function capitalize(string) {
+     *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+     * }
+     *
+     * _.mixin({ 'capitalize': capitalize });
+     * _.capitalize('fred');
+     * // => 'Fred'
+     *
+     * _('fred').capitalize().value();
+     * // => 'Fred'
+     *
+     * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
+     * _('fred').capitalize();
+     * // => 'Fred'
+     */
+    function mixin(object, source, options) {
+      var chain = true,
+          methodNames = source && functions(source);
+
+      if (!source || (!options && !methodNames.length)) {
+        if (options == null) {
+          options = source;
+        }
+        ctor = lodashWrapper;
+        source = object;
+        object = lodash;
+        methodNames = functions(source);
+      }
+      if (options === false) {
+        chain = false;
+      } else if (isObject(options) && 'chain' in options) {
+        chain = options.chain;
+      }
+      var ctor = object,
+          isFunc = isFunction(ctor);
+
+      forEach(methodNames, function(methodName) {
+        var func = object[methodName] = source[methodName];
+        if (isFunc) {
+          ctor.prototype[methodName] = function() {
+            var chainAll = this.__chain__,
+                value = this.__wrapped__,
+                args = [value];
+
+            push.apply(args, arguments);
+            var result = func.apply(object, args);
+            if (chain || chainAll) {
+              if (value === result && isObject(result)) {
+                return this;
+              }
+              result = new ctor(result);
+              result.__chain__ = chainAll;
+            }
+            return result;
+          };
+        }
+      });
+    }
+
+    /**
+     * Reverts the '_' variable to its previous value and returns a reference to
+     * the `lodash` function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @returns {Function} Returns the `lodash` function.
+     * @example
+     *
+     * var lodash = _.noConflict();
+     */
+    function noConflict() {
+      context._ = oldDash;
+      return this;
+    }
+
+    /**
+     * A no-operation function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @example
+     *
+     * var object = { 'name': 'fred' };
+     * _.noop(object) === undefined;
+     * // => true
+     */
+    function noop() {
+      // no operation performed
+    }
+
+    /**
+     * Gets the number of milliseconds that have elapsed since the Unix epoch
+     * (1 January 1970 00:00:00 UTC).
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @example
+     *
+     * var stamp = _.now();
+     * _.defer(function() { console.log(_.now() - stamp); });
+     * // => logs the number of milliseconds it took for the deferred function to be called
+     */
+    var now = isNative(now = Date.now) && now || function() {
+      return new Date().getTime();
+    };
+
+    /**
+     * Converts the given value into an integer of the specified radix.
+     * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
+     * `value` is a hexadecimal, in which case a `radix` of `16` is used.
+     *
+     * Note: This method avoids differences in native ES3 and ES5 `parseInt`
+     * implementations. See http://es5.github.io/#E.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} value The value to parse.
+     * @param {number} [radix] The radix used to interpret the value to parse.
+     * @returns {number} Returns the new integer value.
+     * @example
+     *
+     * _.parseInt('08');
+     * // => 8
+     */
+    var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
+      // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
+      return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
+    };
+
+    /**
+     * Creates a "_.pluck" style function, which returns the `key` value of a
+     * given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} key The name of the property to retrieve.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'fred',   'age': 40 },
+     *   { 'name': 'barney', 'age': 36 }
+     * ];
+     *
+     * var getName = _.property('name');
+     *
+     * _.map(characters, getName);
+     * // => ['barney', 'fred']
+     *
+     * _.sortBy(characters, getName);
+     * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
+     */
+    function property(key) {
+      return function(object) {
+        return object[key];
+      };
+    }
+
+    /**
+     * Produces a random number between `min` and `max` (inclusive). If only one
+     * argument is provided a number between `0` and the given number will be
+     * returned. If `floating` is truey or either `min` or `max` are floats a
+     * floating-point number will be returned instead of an integer.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {number} [min=0] The minimum possible value.
+     * @param {number} [max=1] The maximum possible value.
+     * @param {boolean} [floating=false] Specify returning a floating-point number.
+     * @returns {number} Returns a random number.
+     * @example
+     *
+     * _.random(0, 5);
+     * // => an integer between 0 and 5
+     *
+     * _.random(5);
+     * // => also an integer between 0 and 5
+     *
+     * _.random(5, true);
+     * // => a floating-point number between 0 and 5
+     *
+     * _.random(1.2, 5.2);
+     * // => a floating-point number between 1.2 and 5.2
+     */
+    function random(min, max, floating) {
+      var noMin = min == null,
+          noMax = max == null;
+
+      if (floating == null) {
+        if (typeof min == 'boolean' && noMax) {
+          floating = min;
+          min = 1;
+        }
+        else if (!noMax && typeof max == 'boolean') {
+          floating = max;
+          noMax = true;
+        }
+      }
+      if (noMin && noMax) {
+        max = 1;
+      }
+      min = +min || 0;
+      if (noMax) {
+        max = min;
+        min = 0;
+      } else {
+        max = +max || 0;
+      }
+      if (floating || min % 1 || max % 1) {
+        var rand = nativeRandom();
+        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
+      }
+      return baseRandom(min, max);
+    }
+
+    /**
+     * Resolves the value of property `key` on `object`. If `key` is a function
+     * it will be invoked with the `this` binding of `object` and its result returned,
+     * else the property value is returned. If `object` is falsey then `undefined`
+     * is returned.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {Object} object The object to inspect.
+     * @param {string} key The name of the property to resolve.
+     * @returns {*} Returns the resolved value.
+     * @example
+     *
+     * var object = {
+     *   'cheese': 'crumpets',
+     *   'stuff': function() {
+     *     return 'nonsense';
+     *   }
+     * };
+     *
+     * _.result(object, 'cheese');
+     * // => 'crumpets'
+     *
+     * _.result(object, 'stuff');
+     * // => 'nonsense'
+     */
+    function result(object, key) {
+      if (object) {
+        var value = object[key];
+        return isFunction(value) ? object[key]() : value;
+      }
+    }
+
+    /**
+     * A micro-templating method that handles arbitrary delimiters, preserves
+     * whitespace, and correctly escapes quotes within interpolated code.
+     *
+     * Note: In the development build, `_.template` utilizes sourceURLs for easier
+     * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+     *
+     * For more information on precompiling templates see:
+     * http://lodash.com/custom-builds
+     *
+     * For more information on Chrome extension sandboxes see:
+     * http://developer.chrome.com/stable/extensions/sandboxingEval.html
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} text The template text.
+     * @param {Object} data The data object used to populate the text.
+     * @param {Object} [options] The options object.
+     * @param {RegExp} [options.escape] The "escape" delimiter.
+     * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+     * @param {Object} [options.imports] An object to import into the template as local variables.
+     * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+     * @param {string} [sourceURL] The sourceURL of the template's compiled source.
+     * @param {string} [variable] The data object variable name.
+     * @returns {Function|string} Returns a compiled function when no `data` object
+     *  is given, else it returns the interpolated text.
+     * @example
+     *
+     * // using the "interpolate" delimiter to create a compiled template
+     * var compiled = _.template('hello <%= name %>');
+     * compiled({ 'name': 'fred' });
+     * // => 'hello fred'
+     *
+     * // using the "escape" delimiter to escape HTML in data property values
+     * _.template('<b><%- value %></b>', { 'value': '<script>' });
+     * // => '<b>&lt;script&gt;</b>'
+     *
+     * // using the "evaluate" delimiter to generate HTML
+     * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
+     * _.template(list, { 'people': ['fred', 'barney'] });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+     * _.template('hello ${ name }', { 'name': 'pebbles' });
+     * // => 'hello pebbles'
+     *
+     * // using the internal `print` function in "evaluate" delimiters
+     * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
+     * // => 'hello barney!'
+     *
+     * // using a custom template delimiters
+     * _.templateSettings = {
+     *   'interpolate': /{{([\s\S]+?)}}/g
+     * };
+     *
+     * _.template('hello {{ name }}!', { 'name': 'mustache' });
+     * // => 'hello mustache!'
+     *
+     * // using the `imports` option to import jQuery
+     * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
+     * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the `sourceURL` option to specify a custom sourceURL for the template
+     * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+     * compiled(data);
+     * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+     *
+     * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+     * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
+     * compiled.source;
+     * // => function(data) {
+     *   var __t, __p = '', __e = _.escape;
+     *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+     *   return __p;
+     * }
+     *
+     * // using the `source` property to inline compiled templates for meaningful
+     * // line numbers in error messages and a stack trace
+     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+     *   var JST = {\
+     *     "main": ' + _.template(mainText).source + '\
+     *   };\
+     * ');
+     */
+    function template(text, data, options) {
+      // based on John Resig's `tmpl` implementation
+      // http://ejohn.org/blog/javascript-micro-templating/
+      // and Laura Doktorova's doT.js
+      // https://github.com/olado/doT
+      var settings = lodash.templateSettings;
+      text = String(text || '');
+
+      // avoid missing dependencies when `iteratorTemplate` is not defined
+      options = iteratorTemplate ? defaults({}, options, settings) : settings;
+
+      var imports = iteratorTemplate && defaults({}, options.imports, settings.imports),
+          importsKeys = iteratorTemplate ? keys(imports) : ['_'],
+          importsValues = iteratorTemplate ? values(imports) : [lodash];
+
+      var isEvaluating,
+          index = 0,
+          interpolate = options.interpolate || reNoMatch,
+          source = "__p += '";
+
+      // compile the regexp to match each delimiter
+      var reDelimiters = RegExp(
+        (options.escape || reNoMatch).source + '|' +
+        interpolate.source + '|' +
+        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+        (options.evaluate || reNoMatch).source + '|$'
+      , 'g');
+
+      text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+        interpolateValue || (interpolateValue = esTemplateValue);
+
+        // escape characters that cannot be included in string literals
+        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+        // replace delimiters with snippets
+        if (escapeValue) {
+          source += "' +\n__e(" + escapeValue + ") +\n'";
+        }
+        if (evaluateValue) {
+          isEvaluating = true;
+          source += "';\n" + evaluateValue + ";\n__p += '";
+        }
+        if (interpolateValue) {
+          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+        }
+        index = offset + match.length;
+
+        // the JS engine embedded in Adobe products requires returning the `match`
+        // string in order to produce the correct `offset` value
+        return match;
+      });
+
+      source += "';\n";
+
+      // if `variable` is not specified, wrap a with-statement around the generated
+      // code to add the data object to the top of the scope chain
+      var variable = options.variable,
+          hasVariable = variable;
+
+      if (!hasVariable) {
+        variable = 'obj';
+        source = 'with (' + variable + ') {\n' + source + '\n}\n';
+      }
+      // cleanup code by stripping empty strings
+      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+        .replace(reEmptyStringMiddle, '$1')
+        .replace(reEmptyStringTrailing, '$1;');
+
+      // frame code as the function body
+      source = 'function(' + variable + ') {\n' +
+        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+        "var __t, __p = '', __e = _.escape" +
+        (isEvaluating
+          ? ', __j = Array.prototype.join;\n' +
+            "function print() { __p += __j.call(arguments, '') }\n"
+          : ';\n'
+        ) +
+        source +
+        'return __p\n}';
+
+      // Use a sourceURL for easier debugging.
+      // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+      var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
+
+      try {
+        var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
+      } catch(e) {
+        e.source = source;
+        throw e;
+      }
+      if (data) {
+        return result(data);
+      }
+      // provide the compiled function's source by its `toString` method, in
+      // supported environments, or the `source` property as a convenience for
+      // inlining compiled templates during the build process
+      result.source = source;
+      return result;
+    }
+
+    /**
+     * Executes the callback `n` times, returning an array of the results
+     * of each callback execution. The callback is bound to `thisArg` and invoked
+     * with one argument; (index).
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {number} n The number of times to execute the callback.
+     * @param {Function} callback The function called per iteration.
+     * @param {*} [thisArg] The `this` binding of `callback`.
+     * @returns {Array} Returns an array of the results of each `callback` execution.
+     * @example
+     *
+     * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+     * // => [3, 6, 4]
+     *
+     * _.times(3, function(n) { mage.castSpell(n); });
+     * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+     *
+     * _.times(3, function(n) { this.cast(n); }, mage);
+     * // => also calls `mage.castSpell(n)` three times
+     */
+    function times(n, callback, thisArg) {
+      n = (n = +n) > -1 ? n : 0;
+      var index = -1,
+          result = Array(n);
+
+      callback = baseCreateCallback(callback, thisArg, 1);
+      while (++index < n) {
+        result[index] = callback(index);
+      }
+      return result;
+    }
+
+    /**
+     * The inverse of `_.escape` this method converts the HTML entities
+     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
+     * corresponding characters.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} string The string to unescape.
+     * @returns {string} Returns the unescaped string.
+     * @example
+     *
+     * _.unescape('Fred, Barney &amp; Pebbles');
+     * // => 'Fred, Barney & Pebbles'
+     */
+    function unescape(string) {
+      return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
+    }
+
+    /**
+     * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utilities
+     * @param {string} [prefix] The value to prefix the ID with.
+     * @returns {string} Returns the unique ID.
+     * @example
+     *
+     * _.uniqueId('contact_');
+     * // => 'contact_104'
+     *
+     * _.uniqueId();
+     * // => '105'
+     */
+    function uniqueId(prefix) {
+      var id = ++idCounter;
+      return String(prefix == null ? '' : prefix) + id;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object that wraps the given value with explicit
+     * method chaining enabled.
+     *
+     * @static
+     * @memberOf _
+     * @category Chaining
+     * @param {*} value The value to wrap.
+     * @returns {Object} Returns the wrapper object.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney',  'age': 36 },
+     *   { 'name': 'fred',    'age': 40 },
+     *   { 'name': 'pebbles', 'age': 1 }
+     * ];
+     *
+     * var youngest = _.chain(characters)
+     *     .sortBy('age')
+     *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
+     *     .first()
+     *     .value();
+     * // => 'pebbles is 1'
+     */
+    function chain(value) {
+      value = new lodashWrapper(value);
+      value.__chain__ = true;
+      return value;
+    }
+
+    /**
+     * Invokes `interceptor` with the `value` as the first argument and then
+     * returns `value`. The purpose of this method is to "tap into" a method
+     * chain in order to perform operations on intermediate results within
+     * the chain.
+     *
+     * @static
+     * @memberOf _
+     * @category Chaining
+     * @param {*} value The value to provide to `interceptor`.
+     * @param {Function} interceptor The function to invoke.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * _([1, 2, 3, 4])
+     *  .tap(function(array) { array.pop(); })
+     *  .reverse()
+     *  .value();
+     * // => [3, 2, 1]
+     */
+    function tap(value, interceptor) {
+      interceptor(value);
+      return value;
+    }
+
+    /**
+     * Enables explicit method chaining on the wrapper object.
+     *
+     * @name chain
+     * @memberOf _
+     * @category Chaining
+     * @returns {*} Returns the wrapper object.
+     * @example
+     *
+     * var characters = [
+     *   { 'name': 'barney', 'age': 36 },
+     *   { 'name': 'fred',   'age': 40 }
+     * ];
+     *
+     * // without explicit chaining
+     * _(characters).first();
+     * // => { 'name': 'barney', 'age': 36 }
+     *
+     * // with explicit chaining
+     * _(characters).chain()
+     *   .first()
+     *   .pick('age')
+     *   .value();
+     * // => { 'age': 36 }
+     */
+    function wrapperChain() {
+      this.__chain__ = true;
+      return this;
+    }
+
+    /**
+     * Produces the `toString` result of the wrapped value.
+     *
+     * @name toString
+     * @memberOf _
+     * @category Chaining
+     * @returns {string} Returns the string result.
+     * @example
+     *
+     * _([1, 2, 3]).toString();
+     * // => '1,2,3'
+     */
+    function wrapperToString() {
+      return String(this.__wrapped__);
+    }
+
+    /**
+     * Extracts the wrapped value.
+     *
+     * @name valueOf
+     * @memberOf _
+     * @alias value
+     * @category Chaining
+     * @returns {*} Returns the wrapped value.
+     * @example
+     *
+     * _([1, 2, 3]).valueOf();
+     * // => [1, 2, 3]
+     */
+    function wrapperValueOf() {
+      return this.__wrapped__;
+    }
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions that return wrapped values when chaining
+    lodash.after = after;
+    lodash.assign = assign;
+    lodash.at = at;
+    lodash.bind = bind;
+    lodash.bindAll = bindAll;
+    lodash.bindKey = bindKey;
+    lodash.chain = chain;
+    lodash.compact = compact;
+    lodash.compose = compose;
+    lodash.constant = constant;
+    lodash.countBy = countBy;
+    lodash.create = create;
+    lodash.createCallback = createCallback;
+    lodash.curry = curry;
+    lodash.debounce = debounce;
+    lodash.defaults = defaults;
+    lodash.defer = defer;
+    lodash.delay = delay;
+    lodash.difference = difference;
+    lodash.filter = filter;
+    lodash.flatten = flatten;
+    lodash.forEach = forEach;
+    lodash.forEachRight = forEachRight;
+    lodash.forIn = forIn;
+    lodash.forInRight = forInRight;
+    lodash.forOwn = forOwn;
+    lodash.forOwnRight = forOwnRight;
+    lodash.functions = functions;
+    lodash.groupBy = groupBy;
+    lodash.indexBy = indexBy;
+    lodash.initial = initial;
+    lodash.intersection = intersection;
+    lodash.invert = invert;
+    lodash.invoke = invoke;
+    lodash.keys = keys;
+    lodash.map = map;
+    lodash.mapValues = mapValues;
+    lodash.max = max;
+    lodash.memoize = memoize;
+    lodash.merge = merge;
+    lodash.min = min;
+    lodash.omit = omit;
+    lodash.once = once;
+    lodash.pairs = pairs;
+    lodash.partial = partial;
+    lodash.partialRight = partialRight;
+    lodash.pick = pick;
+    lodash.pluck = pluck;
+    lodash.property = property;
+    lodash.pull = pull;
+    lodash.range = range;
+    lodash.reject = reject;
+    lodash.remove = remove;
+    lodash.rest = rest;
+    lodash.shuffle = shuffle;
+    lodash.sortBy = sortBy;
+    lodash.tap = tap;
+    lodash.throttle = throttle;
+    lodash.times = times;
+    lodash.toArray = toArray;
+    lodash.transform = transform;
+    lodash.union = union;
+    lodash.uniq = uniq;
+    lodash.values = values;
+    lodash.where = where;
+    lodash.without = without;
+    lodash.wrap = wrap;
+    lodash.xor = xor;
+    lodash.zip = zip;
+    lodash.zipObject = zipObject;
+
+    // add aliases
+    lodash.collect = map;
+    lodash.drop = rest;
+    lodash.each = forEach;
+    lodash.eachRight = forEachRight;
+    lodash.extend = assign;
+    lodash.methods = functions;
+    lodash.object = zipObject;
+    lodash.select = filter;
+    lodash.tail = rest;
+    lodash.unique = uniq;
+    lodash.unzip = zip;
+
+    // add functions to `lodash.prototype`
+    mixin(lodash);
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions that return unwrapped values when chaining
+    lodash.clone = clone;
+    lodash.cloneDeep = cloneDeep;
+    lodash.contains = contains;
+    lodash.escape = escape;
+    lodash.every = every;
+    lodash.find = find;
+    lodash.findIndex = findIndex;
+    lodash.findKey = findKey;
+    lodash.findLast = findLast;
+    lodash.findLastIndex = findLastIndex;
+    lodash.findLastKey = findLastKey;
+    lodash.has = has;
+    lodash.identity = identity;
+    lodash.indexOf = indexOf;
+    lodash.isArguments = isArguments;
+    lodash.isArray = isArray;
+    lodash.isBoolean = isBoolean;
+    lodash.isDate = isDate;
+    lodash.isElement = isElement;
+    lodash.isEmpty = isEmpty;
+    lodash.isEqual = isEqual;
+    lodash.isFinite = isFinite;
+    lodash.isFunction = isFunction;
+    lodash.isNaN = isNaN;
+    lodash.isNull = isNull;
+    lodash.isNumber = isNumber;
+    lodash.isObject = isObject;
+    lodash.isPlainObject = isPlainObject;
+    lodash.isRegExp = isRegExp;
+    lodash.isString = isString;
+    lodash.isUndefined = isUndefined;
+    lodash.lastIndexOf = lastIndexOf;
+    lodash.mixin = mixin;
+    lodash.noConflict = noConflict;
+    lodash.noop = noop;
+    lodash.now = now;
+    lodash.parseInt = parseInt;
+    lodash.random = random;
+    lodash.reduce = reduce;
+    lodash.reduceRight = reduceRight;
+    lodash.result = result;
+    lodash.runInContext = runInContext;
+    lodash.size = size;
+    lodash.some = some;
+    lodash.sortedIndex = sortedIndex;
+    lodash.template = template;
+    lodash.unescape = unescape;
+    lodash.uniqueId = uniqueId;
+
+    // add aliases
+    lodash.all = every;
+    lodash.any = some;
+    lodash.detect = find;
+    lodash.findWhere = find;
+    lodash.foldl = reduce;
+    lodash.foldr = reduceRight;
+    lodash.include = contains;
+    lodash.inject = reduce;
+
+    mixin(function() {
+      var source = {}
+      forOwn(lodash, function(func, methodName) {
+        if (!lodash.prototype[methodName]) {
+          source[methodName] = func;
+        }
+      });
+      return source;
+    }(), false);
+
+    /*--------------------------------------------------------------------------*/
+
+    // add functions capable of returning wrapped and unwrapped values when chaining
+    lodash.first = first;
+    lodash.last = last;
+    lodash.sample = sample;
+
+    // add aliases
+    lodash.take = first;
+    lodash.head = first;
+
+    forOwn(lodash, function(func, methodName) {
+      var callbackable = methodName !== 'sample';
+      if (!lodash.prototype[methodName]) {
+        lodash.prototype[methodName]= function(n, guard) {
+          var chainAll = this.__chain__,
+              result = func(this.__wrapped__, n, guard);
+
+          return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
+            ? result
+            : new lodashWrapper(result, chainAll);
+        };
+      }
+    });
+
+    /*--------------------------------------------------------------------------*/
+
+    /**
+     * The semantic version number.
+     *
+     * @static
+     * @memberOf _
+     * @type string
+     */
+    lodash.VERSION = '2.4.1';
+
+    // add "Chaining" functions to the wrapper
+    lodash.prototype.chain = wrapperChain;
+    lodash.prototype.toString = wrapperToString;
+    lodash.prototype.value = wrapperValueOf;
+    lodash.prototype.valueOf = wrapperValueOf;
+
+    // add `Array` functions that return unwrapped values
+    baseEach(['join', 'pop', 'shift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        var chainAll = this.__chain__,
+            result = func.apply(this.__wrapped__, arguments);
+
+        return chainAll
+          ? new lodashWrapper(result, chainAll)
+          : result;
+      };
+    });
+
+    // add `Array` functions that return the existing wrapped value
+    baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        func.apply(this.__wrapped__, arguments);
+        return this;
+      };
+    });
+
+    // add `Array` functions that return new wrapped values
+    baseEach(['concat', 'slice', 'splice'], function(methodName) {
+      var func = arrayRef[methodName];
+      lodash.prototype[methodName] = function() {
+        return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
+      };
+    });
+
+    // avoid array-like object bugs with `Array#shift` and `Array#splice`
+    // in IE < 9, Firefox < 10, Narwhal, and RingoJS
+    if (!support.spliceObjects) {
+      baseEach(['pop', 'shift', 'splice'], function(methodName) {
+        var func = arrayRef[methodName],
+            isSplice = methodName == 'splice';
+
+        lodash.prototype[methodName] = function() {
+          var chainAll = this.__chain__,
+              value = this.__wrapped__,
+              result = func.apply(value, arguments);
+
+          if (value.length === 0) {
+            delete value[0];
+          }
+          return (chainAll || isSplice)
+            ? new lodashWrapper(result, chainAll)
+            : result;
+        };
+      });
+    }
+
+    // add pseudo private property to be used and removed during the build process
+    lodash._baseEach = baseEach;
+    lodash._iteratorTemplate = iteratorTemplate;
+    lodash._shimKeys = shimKeys;
+
+    return lodash;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // expose Lo-Dash
+  var _ = runInContext();
+
+  // some AMD build optimizers like r.js check for condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose Lo-Dash to the global object even when an AMD loader is present in
+    // case Lo-Dash is loaded with a RequireJS shim config.
+    // See http://requirejs.org/docs/api.html#config-shim
+    root._ = _;
+
+    // define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module
+    define(function() {
+      return _;
+    });
+  }
+  // check for `exports` after `define` in case a build optimizer adds an `exports` object
+  else if (freeExports && freeModule) {
+    // in Node.js or RingoJS
+    if (moduleExports) {
+      (freeModule.exports = _)._ = _;
+    }
+    // in Narwhal or Rhino -require
+    else {
+      freeExports._ = _;
+    }
+  }
+  else {
+    // in a browser or Rhino
+    root._ = _;
+  }
+}.call(this));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/lodash/package.json	(revision 533)
@@ -0,0 +1,106 @@
+{
+  "name": "lodash",
+  "version": "2.4.1",
+  "description": "A utility library delivering consistency, customization, performance, & extras.",
+  "homepage": "http://lodash.com/",
+  "license": "MIT",
+  "main": "dist/lodash.js",
+  "keywords": [
+    "amd",
+    "browser",
+    "client",
+    "customize",
+    "functional",
+    "server",
+    "util"
+  ],
+  "author": {
+    "name": "John-David Dalton",
+    "email": "john.david.dalton@gmail.com",
+    "url": "http://allyoucanleet.com/"
+  },
+  "contributors": [
+    {
+      "name": "John-David Dalton",
+      "email": "john.david.dalton@gmail.com",
+      "url": "http://allyoucanleet.com/"
+    },
+    {
+      "name": "Blaine Bublitz",
+      "email": "blaine@iceddev.com",
+      "url": "http://www.iceddev.com/"
+    },
+    {
+      "name": "Kit Cambridge",
+      "email": "github@kitcambridge.be",
+      "url": "http://kitcambridge.be/"
+    },
+    {
+      "name": "Mathias Bynens",
+      "email": "mathias@qiwi.be",
+      "url": "http://mathiasbynens.be/"
+    }
+  ],
+  "bugs": {
+    "url": "https://github.com/lodash/lodash/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/lodash/lodash.git"
+  },
+  "engines": [
+    "node",
+    "rhino"
+  ],
+  "files": [
+    "LICENSE.txt",
+    "lodash.js",
+    "dist/lodash.js",
+    "dist/lodash.min.js",
+    "dist/lodash.compat.js",
+    "dist/lodash.compat.min.js",
+    "dist/lodash.underscore.js",
+    "dist/lodash.underscore.min.js"
+  ],
+  "jam": {
+    "main": "dist/lodash.compat.js",
+    "include": [
+      "LICENSE.txt",
+      "dist/lodash.js",
+      "dist/lodash.min.js",
+      "dist/lodash.compat.js",
+      "dist/lodash.compat.min.js",
+      "dist/lodash.underscore.js",
+      "dist/lodash.underscore.min.js"
+    ]
+  },
+  "volo": {
+    "type": "directory",
+    "ignore": [
+      ".*",
+      "*.custom.*",
+      "*.min.*",
+      "*.template.*",
+      "*.map",
+      "*.md",
+      "lodash.js",
+      "index.js",
+      "bower.json",
+      "component.json",
+      "doc",
+      "modularize",
+      "node_modules",
+      "perf",
+      "test",
+      "vendor"
+    ]
+  },
+  "readme": "# Lo-Dash v2.4.1\nA utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features).\n\n## Download\n\nCheck out our [wiki]([https://github.com/lodash/lodash/wiki/build-differences]) for details over the differences between builds.\n\n* Modern builds perfect for newer browsers/environments:<br>\n[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.js) &\n[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.min.js)\n\n* Compatibility builds for older environment support too:<br>\n[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.js) &\n[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.compat.min.js)\n\n* Underscore builds to use as a drop-in replacement:<br>\n[Development](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js) &\n[Production](https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.min.js)\n\nCDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash). For smaller file sizes, create [custom builds](http://lodash.com/custom-builds) with only the features needed.\n\nLove modules? Weâve got you covered with [lodash-amd](https://npmjs.org/package/lodash-amd), [lodash-es6](https://github.com/lodash/lodash-es6), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method.\n\n## Dive in\n\nThereâs plenty of **[documentation](http://lodash.com/docs)**, [unit tests](http://lodash.com/tests), & [benchmarks](http://lodash.com/benchmarks).<br>\nCheck out <a href=\"http://devdocs.io/lodash/\">DevDocs</a> as a fast, organized, & searchable interface for our documentation.\n\nThe full changelog for this release is available on our [wiki](https://github.com/lodash/lodash/wiki/Changelog).<br>\nA list of upcoming features is available on our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap).\n\n## Features *not* in Underscore\n\n * AMD loader support ([curl](https://github.com/cujojs/curl), [dojo](http://dojotoolkit.org/), [requirejs](http://requirejs.org/), etc.)\n * [_(âŠ)](http://lodash.com/docs#_) supports intuitive chaining\n * [_.at](http://lodash.com/docs#at) for cherry-picking collection values\n * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*âlazyâ*](http://michaux.ca/articles/lazy-function-definition-pattern) defined methods\n * [_.clone](http://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects\n * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects\n * [_.constant](http://lodash.com/docs#constant) & [_.property](http://lodash.com/docs#property) function generators for composing functions\n * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex`\n * [_.create](http://lodash.com/docs#create) for easier object inheritance\n * [_.createCallback](http://lodash.com/docs#createCallback) for extending callbacks in methods & mixins\n * [_.curry](http://lodash.com/docs#curry) for creating [curried](http://hughfdjackson.com/javascript/2013/07/06/why-curry-helps/) functions\n * [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) accept additional `options` for more control\n * [_.findIndex](http://lodash.com/docs#findIndex) & [_.findKey](http://lodash.com/docs#findKey) for finding indexes & keys\n * [_.forEach](http://lodash.com/docs#forEach) is chainable & supports exiting early\n * [_.forIn](http://lodash.com/docs#forIn) for iterating own & inherited properties\n * [_.forOwn](http://lodash.com/docs#forOwn) for iterating own properties\n * [_.isPlainObject](http://lodash.com/docs#isPlainObject) for checking if values are created by `Object`\n * [_.mapValues](http://lodash.com/docs#mapValues) for [mapping](http://lodash.com/docs#map) values to an object\n * [_.memoize](http://lodash.com/docs#memoize) exposes the `cache` of memoized functions\n * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)\n * [_.noop](http://lodash.com/docs#noop) for function placeholders\n * [_.now](http://lodash.com/docs#now) as a cross-browser `Date.now` alternative\n * [_.parseInt](http://lodash.com/docs#parseInt) for consistent behavior\n * [_.pull](http://lodash.com/docs#pull) & [_.remove](http://lodash.com/docs#remove) for mutating arrays\n * [_.random](http://lodash.com/docs#random) supports returning floating-point numbers\n * [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking\n * [_.sortBy](http://lodash.com/docs#sortBy) supports sorting by multiple properties\n * [_.support](http://lodash.com/docs#support) for flagging environment features\n * [_.template](http://lodash.com/docs#template) supports [*âimportsâ*](http://lodash.com/docs#templateSettings_imports) options & [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals)\n * [_.transform](http://lodash.com/docs#transform) as a powerful alternative to [_.reduce](http://lodash.com/docs#reduce) for transforming objects\n * [_.where](http://lodash.com/docs#where) supports deep object comparisons\n * [_.xor](http://lodash.com/docs#xor) as a companion to [_.difference](http://lodash.com/docs#difference), [_.intersection](http://lodash.com/docs#intersection), & [_.union](http://lodash.com/docs#union)\n * [_.zip](http://lodash.com/docs#zip) is capable of unzipping values\n * [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick), &\n   [more](http://lodash.com/docs \"_.assign, _.clone, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest\") accept callbacks\n * [_.contains](http://lodash.com/docs#contains), [_.toArray](http://lodash.com/docs#toArray), &\n   [more](http://lodash.com/docs \"_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.forEachRight, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.size, _.some, _.sortBy, _.where\") accept strings\n * [_.filter](http://lodash.com/docs#filter), [_.map](http://lodash.com/docs#map), &\n   [more](http://lodash.com/docs \"_.countBy, _.every, _.find, _.findKey, _.findLast, _.findLastIndex, _.findLastKey, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq\") support *â_.pluckâ* & *â_.whereâ* shorthands\n * [_.findLast](http://lodash.com/docs#findLast), [_.findLastIndex](http://lodash.com/docs#findLastIndex), &\n   [more](http://lodash.com/docs \"_.findLastKey, _.forEachRight, _.forInRight, _.forOwnRight, _.partialRight\") right-associative methods\n\n## Resources\n\n * Podcasts\n  - [JavaScript Jabber](http://javascriptjabber.com/079-jsj-lo-dash-with-john-david-dalton/)\n\n * Posts\n  - [Say âHelloâ to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)\n  - [Custom builds in Lo-Dash 2.0](http://kitcambridge.be/blog/custom-builds-in-lo-dash-2-dot-0/)\n\n * Videos\n  - [Introduction](https://vimeo.com/44154599)\n  - [Origins](https://vimeo.com/44154600)\n  - [Optimizations & builds](https://vimeo.com/44154601)\n  - [Native method use](https://vimeo.com/48576012)\n  - [Testing](https://vimeo.com/45865290)\n  - [CascadiaJS â12](http://www.youtube.com/watch?v=dpPy4f_SeEk)\n\n A list of other community created podcasts, posts, & videos is available on our [wiki](https://github.com/lodash/lodash/wiki/Resources).\n\n## Support\n\nTested in Chrome 5~31, Firefox 2~25, IE 6-11, Opera 9.25~17, Safari 3-7, Node.js 0.6.21~0.10.22, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5.<br>\nAutomated browser test results [are available](https://saucelabs.com/u/lodash) as well as [Travis CI](https://travis-ci.org/) builds for [lodash](https://travis-ci.org/lodash/lodash/), [lodash-cli](https://travis-ci.org/lodash/lodash-cli/), [lodash-amd](https://travis-ci.org/lodash/lodash-amd/), [lodash-node](https://travis-ci.org/lodash/lodash-node/), & [grunt-lodash](https://travis-ci.org/lodash/grunt-lodash).\n\nSpecial thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing.<br>\n[![Sauce Labs](http://lodash.com/_img/sauce.png)](https://saucelabs.com/ \"Sauce Labs: Selenium Testing & More\")\n\n## Installation & usage\n\nIn browsers:\n\n```html\n<script src=\"lodash.js\"></script>\n```\n\nUsing [`npm`](http://npmjs.org/):\n\n```bash\nnpm i --save lodash\n\n{sudo} npm i -g lodash\nnpm ln lodash\n```\n\nIn [Node.js](http://nodejs.org/) & [Ringo](http://ringojs.org/):\n\n```js\nvar _ = require('lodash');\n// or as Underscore\nvar _ = require('lodash/dist/lodash.underscore');\n```\n\n**Notes:**\n * Donât assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL\n * If Lo-Dash is installed globally, run [`npm ln lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projectâs root directory *before* requiring it\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('lodash.js');\n```\n\nIn an AMD loader:\n\n```js\nrequire({\n  'packages': [\n    { 'name': 'lodash', 'location': 'path/to/lodash', 'main': 'lodash' }\n  ]\n},\n['lodash'], function(_) {\n  console.log(_.VERSION);\n});\n```\n\n## Author\n\n| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton \"Follow @jdalton on Twitter\") |\n|---|\n| [John-David Dalton](http://allyoucanleet.com/) |\n\n## Contributors\n\n| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](https://twitter.com/blainebublitz \"Follow @BlaineBublitz on Twitter\") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias \"Follow @mathias on Twitter\") |\n|---|---|---|\n| [Blaine Bublitz](http://www.iceddev.com/) | [Kit Cambridge](http://kitcambridge.be/) | [Mathias Bynens](http://mathiasbynens.be/) |\n\n[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/lodash/lodash/trend.png)](https://bitdeli.com/free \"Bitdeli Badge\")\n",
+  "readmeFilename": "README.md",
+  "_id": "lodash@2.4.1",
+  "dist": {
+    "shasum": "94a1b72c8f82dcf3808893328a2d1e6003189035"
+  },
+  "_from": "lodash@~2.4.1",
+  "_resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+examples
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/.travis.yml
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/.travis.yml	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/.travis.yml	(revision 533)
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+  - 0.8
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/LICENSE-MIT
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/LICENSE-MIT	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/LICENSE-MIT	(revision 533)
@@ -0,0 +1,22 @@
+Copyright (c) 2012-2013 Mickael Daniel
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/bin/tiny-lr
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/bin/tiny-lr	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/bin/tiny-lr	(revision 533)
@@ -0,0 +1,68 @@
+#!/usr/bin/env node
+
+var fs    = require('fs');
+var path  = require('path');
+
+// default DEBUG if not set already
+process.env.DEBUG = process.env.DEBUG || 'tinylr tinylr:*';
+
+var Server = require('..').Server;
+var noptify = require('noptify');
+
+var program = noptify(process.argv, { program: 'tiny-lr' })
+  .version('0.0.1')
+  .option('port', '-p', 'Port to listen on (default: 35729)', Number)
+  .option('pid', 'Path to the generated PID file (default: ./tiny-lr.pid)', String);
+
+var opts = program.parse();
+opts.port = opts.port || 35729;
+opts.pid = opts.pid || path.resolve('tiny-lr.pid');
+
+// if it was required, don't start the server and expose the Server object.
+if (module.parent) {
+  module.exports = Server;
+  return;
+}
+
+// Server
+
+// Thanks to @FGRibreau for his very simple and very handy gist:
+// https://gist.github.com/1846952
+
+process.title = 'tiny-lr';
+
+process.on('exit', function() {
+  console.log('... Closing server ...');
+  console.log('... Removing pid file (%s) ...', opts.pid);
+  fs.unlinkSync(opts.pid);
+});
+
+process.on('SIGTERM', function() {
+  return process.exit(0);
+});
+
+process.on('SIGINT', function() {
+  return process.exit(0);
+});
+
+
+var srv = new Server(opts);
+
+srv.on('close', function() {
+  process.nextTick(function() {
+    process.exit();
+  });
+});
+
+console.log();
+srv.listen(opts.port, function(err) {
+  fs.writeFile(opts.pid, process.pid, function(err) {
+    if(err) {
+      console.log('... Cannot write pid file: %s', opts.pid);
+      process.exit(1)
+    }
+
+    console.log('... Listening on %s (pid: %s) ...', opts.port, process.pid);
+    console.log('... pid file: %s', opts.pid);
+  });
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/bin/update-livereload
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/bin/update-livereload	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/bin/update-livereload	(revision 533)
@@ -0,0 +1,13 @@
+#!/usr/bin/env node
+
+var fs      = require('fs');
+var path    = require('path');
+var request = require('request');
+
+var file = path.join(__dirname, '..', 'lib/public/livereload.js');
+var url = process.argv.slice(2)[0] || 'https://raw.github.com/livereload/livereload-js/master/dist/livereload.js';
+
+console.error('Updating livereload.js %s from %s', file, url);
+request(url)
+  .pipe(fs.createWriteStream(file))
+  .on('close', console.log.bind(console, 'Done'));
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/client.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/client.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/client.js	(revision 533)
@@ -0,0 +1,81 @@
+
+var util      = require('util');
+var events    = require('events');
+var WebSocket = require('faye-websocket');
+
+module.exports = Client;
+
+function Client(req, socket, head, options) {
+  options = this.options = options || {};
+  this.ws = new WebSocket(req, socket, head);
+  this.ws.onmessage = this.message.bind(this);
+  this.ws.onclose = this.close.bind(this);
+  this.id = this.uniqueId('ws');
+}
+
+util.inherits(Client, events.EventEmitter);
+
+Client.prototype.message = function message(event) {
+  var data = this.data(event);
+  if(this[data.command]) return this[data.command](data);
+};
+
+Client.prototype.close = function close(event) {
+  if(this.ws) {
+    this.ws.close();
+    this.ws = null;
+  }
+
+  this.emit('end', event);
+};
+
+// Commands
+
+Client.prototype.hello = function hello() {
+  this.send({
+    command: 'hello',
+    protocols: [
+      'http://livereload.com/protocols/official-7'
+    ],
+    serverName: 'tiny-lr'
+  });
+};
+
+Client.prototype.info = function info(data) {
+  this.plugins = data.plugins;
+  this.url = data.url;
+};
+
+// Server commands
+
+Client.prototype.reload = function reload(files) {
+  files.forEach(function(file) {
+    this.send({
+      command: 'reload',
+      path: file,
+      liveCss: this.options.liveCss !== false,
+      liveJs: this.options.liveJs !== false,
+      liveImg: this.options.liveImg !== false
+    });
+  }, this);
+};
+
+// Utilities
+
+Client.prototype.data = function _data(event) {
+  var data = {};
+  try {
+    data = JSON.parse(event.data);
+  } catch (e) {}
+  return data;
+};
+
+Client.prototype.send = function send(data) {
+  this.ws.send(JSON.stringify(data));
+};
+
+var idCounter = 0;
+Client.prototype.uniqueId = function uniqueId(prefix) {
+  var id = idCounter++;
+  return prefix ? prefix + id : id;
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/index.js	(revision 533)
@@ -0,0 +1,22 @@
+
+var Server = require('./server');
+var Client = require('./client');
+
+module.exports = tinylr;
+tinylr.Server = Server;
+tinylr.Client = Client;
+
+tinylr.middleware = middleware;
+
+function tinylr(opts) {
+  return new Server(opts);
+}
+
+var util = require('util');
+
+function middleware(opts) {
+  var srv = new Server(opts);
+  return function tinylr(req, res, next) {
+    srv.handler(req, res, next);
+  };
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/public/livereload.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/public/livereload.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/public/livereload.js	(revision 533)
@@ -0,0 +1,1060 @@
+(function() {
+var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __less = {}, __startup = {};
+
+// customevents
+var CustomEvents;
+CustomEvents = {
+  bind: function(element, eventName, handler) {
+    if (element.addEventListener) {
+      return element.addEventListener(eventName, handler, false);
+    } else if (element.attachEvent) {
+      element[eventName] = 1;
+      return element.attachEvent('onpropertychange', function(event) {
+        if (event.propertyName === eventName) {
+          return handler();
+        }
+      });
+    } else {
+      throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement");
+    }
+  },
+  fire: function(element, eventName) {
+    var event;
+    if (element.addEventListener) {
+      event = document.createEvent('HTMLEvents');
+      event.initEvent(eventName, true, true);
+      return document.dispatchEvent(event);
+    } else if (element.attachEvent) {
+      if (element[eventName]) {
+        return element[eventName]++;
+      }
+    } else {
+      throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement");
+    }
+  }
+};
+__customevents.bind = CustomEvents.bind;
+__customevents.fire = CustomEvents.fire;
+
+// protocol
+var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError;
+var __indexOf = Array.prototype.indexOf || function(item) {
+  for (var i = 0, l = this.length; i < l; i++) {
+    if (this[i] === item) return i;
+  }
+  return -1;
+};
+__protocol.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6';
+__protocol.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7';
+__protocol.ProtocolError = ProtocolError = (function() {
+  function ProtocolError(reason, data) {
+    this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\".";
+  }
+  return ProtocolError;
+})();
+__protocol.Parser = Parser = (function() {
+  function Parser(handlers) {
+    this.handlers = handlers;
+    this.reset();
+  }
+  Parser.prototype.reset = function() {
+    return this.protocol = null;
+  };
+  Parser.prototype.process = function(data) {
+    var command, message, options, _ref;
+    try {
+      if (!(this.protocol != null)) {
+        if (data.match(/^!!ver:([\d.]+)$/)) {
+          this.protocol = 6;
+        } else if (message = this._parseMessage(data, ['hello'])) {
+          if (!message.protocols.length) {
+            throw new ProtocolError("no protocols specified in handshake message");
+          } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) {
+            this.protocol = 7;
+          } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) {
+            this.protocol = 6;
+          } else {
+            throw new ProtocolError("no supported protocols found");
+          }
+        }
+        return this.handlers.connected(this.protocol);
+      } else if (this.protocol === 6) {
+        message = JSON.parse(data);
+        if (!message.length) {
+          throw new ProtocolError("protocol 6 messages must be arrays");
+        }
+        command = message[0], options = message[1];
+        if (command !== 'refresh') {
+          throw new ProtocolError("unknown protocol 6 command");
+        }
+        return this.handlers.message({
+          command: 'reload',
+          path: options.path,
+          liveCSS: (_ref = options.apply_css_live) != null ? _ref : true
+        });
+      } else {
+        message = this._parseMessage(data, ['reload', 'alert']);
+        return this.handlers.message(message);
+      }
+    } catch (e) {
+      if (e instanceof ProtocolError) {
+        return this.handlers.error(e);
+      } else {
+        throw e;
+      }
+    }
+  };
+  Parser.prototype._parseMessage = function(data, validCommands) {
+    var message, _ref;
+    try {
+      message = JSON.parse(data);
+    } catch (e) {
+      throw new ProtocolError('unparsable JSON', data);
+    }
+    if (!message.command) {
+      throw new ProtocolError('missing "command" key', data);
+    }
+    if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) {
+      throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data);
+    }
+    return message;
+  };
+  return Parser;
+})();
+
+// connector
+// Generated by CoffeeScript 1.3.3
+var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref;
+
+_ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7;
+
+Version = '2.0.8';
+
+__connector.Connector = Connector = (function() {
+
+  function Connector(options, WebSocket, Timer, handlers) {
+    var _this = this;
+    this.options = options;
+    this.WebSocket = WebSocket;
+    this.Timer = Timer;
+    this.handlers = handlers;
+    this._uri = "ws" + (this.options.https ? "s" : "") + "://" + this.options.host + ":" + this.options.port + "/livereload";
+    this._nextDelay = this.options.mindelay;
+    this._connectionDesired = false;
+    this.protocol = 0;
+    this.protocolParser = new Parser({
+      connected: function(protocol) {
+        _this.protocol = protocol;
+        _this._handshakeTimeout.stop();
+        _this._nextDelay = _this.options.mindelay;
+        _this._disconnectionReason = 'broken';
+        return _this.handlers.connected(protocol);
+      },
+      error: function(e) {
+        _this.handlers.error(e);
+        return _this._closeOnError();
+      },
+      message: function(message) {
+        return _this.handlers.message(message);
+      }
+    });
+    this._handshakeTimeout = new Timer(function() {
+      if (!_this._isSocketConnected()) {
+        return;
+      }
+      _this._disconnectionReason = 'handshake-timeout';
+      return _this.socket.close();
+    });
+    this._reconnectTimer = new Timer(function() {
+      if (!_this._connectionDesired) {
+        return;
+      }
+      return _this.connect();
+    });
+    this.connect();
+  }
+
+  Connector.prototype._isSocketConnected = function() {
+    return this.socket && this.socket.readyState === this.WebSocket.OPEN;
+  };
+
+  Connector.prototype.connect = function() {
+    var _this = this;
+    this._connectionDesired = true;
+    if (this._isSocketConnected()) {
+      return;
+    }
+    this._reconnectTimer.stop();
+    this._disconnectionReason = 'cannot-connect';
+    this.protocolParser.reset();
+    this.handlers.connecting();
+    this.socket = new this.WebSocket(this._uri);
+    this.socket.onopen = function(e) {
+      return _this._onopen(e);
+    };
+    this.socket.onclose = function(e) {
+      return _this._onclose(e);
+    };
+    this.socket.onmessage = function(e) {
+      return _this._onmessage(e);
+    };
+    return this.socket.onerror = function(e) {
+      return _this._onerror(e);
+    };
+  };
+
+  Connector.prototype.disconnect = function() {
+    this._connectionDesired = false;
+    this._reconnectTimer.stop();
+    if (!this._isSocketConnected()) {
+      return;
+    }
+    this._disconnectionReason = 'manual';
+    return this.socket.close();
+  };
+
+  Connector.prototype._scheduleReconnection = function() {
+    if (!this._connectionDesired) {
+      return;
+    }
+    if (!this._reconnectTimer.running) {
+      this._reconnectTimer.start(this._nextDelay);
+      return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2);
+    }
+  };
+
+  Connector.prototype.sendCommand = function(command) {
+    if (this.protocol == null) {
+      return;
+    }
+    return this._sendCommand(command);
+  };
+
+  Connector.prototype._sendCommand = function(command) {
+    return this.socket.send(JSON.stringify(command));
+  };
+
+  Connector.prototype._closeOnError = function() {
+    this._handshakeTimeout.stop();
+    this._disconnectionReason = 'error';
+    return this.socket.close();
+  };
+
+  Connector.prototype._onopen = function(e) {
+    var hello;
+    this.handlers.socketConnected();
+    this._disconnectionReason = 'handshake-failed';
+    hello = {
+      command: 'hello',
+      protocols: [PROTOCOL_6, PROTOCOL_7]
+    };
+    hello.ver = Version;
+    if (this.options.ext) {
+      hello.ext = this.options.ext;
+    }
+    if (this.options.extver) {
+      hello.extver = this.options.extver;
+    }
+    if (this.options.snipver) {
+      hello.snipver = this.options.snipver;
+    }
+    this._sendCommand(hello);
+    return this._handshakeTimeout.start(this.options.handshake_timeout);
+  };
+
+  Connector.prototype._onclose = function(e) {
+    this.protocol = 0;
+    this.handlers.disconnected(this._disconnectionReason, this._nextDelay);
+    return this._scheduleReconnection();
+  };
+
+  Connector.prototype._onerror = function(e) {};
+
+  Connector.prototype._onmessage = function(e) {
+    return this.protocolParser.process(e.data);
+  };
+
+  return Connector;
+
+})();
+
+// timer
+var Timer;
+var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+__timer.Timer = Timer = (function() {
+  function Timer(func) {
+    this.func = func;
+    this.running = false;
+    this.id = null;
+    this._handler = __bind(function() {
+      this.running = false;
+      this.id = null;
+      return this.func();
+    }, this);
+  }
+  Timer.prototype.start = function(timeout) {
+    if (this.running) {
+      clearTimeout(this.id);
+    }
+    this.id = setTimeout(this._handler, timeout);
+    return this.running = true;
+  };
+  Timer.prototype.stop = function() {
+    if (this.running) {
+      clearTimeout(this.id);
+      this.running = false;
+      return this.id = null;
+    }
+  };
+  return Timer;
+})();
+Timer.start = function(timeout, func) {
+  return setTimeout(func, timeout);
+};
+
+// options
+var Options;
+__options.Options = Options = (function() {
+  function Options() {
+    this.https = false;
+    this.host = null;
+    this.port = 35729;
+    this.snipver = null;
+    this.ext = null;
+    this.extver = null;
+    this.mindelay = 1000;
+    this.maxdelay = 60000;
+    this.handshake_timeout = 5000;
+  }
+  Options.prototype.set = function(name, value) {
+    switch (typeof this[name]) {
+      case 'undefined':
+        break;
+      case 'number':
+        return this[name] = +value;
+      default:
+        return this[name] = value;
+    }
+  };
+  return Options;
+})();
+Options.extract = function(document) {
+  var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len2, _ref, _ref2;
+  _ref = document.getElementsByTagName('script');
+  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+    element = _ref[_i];
+    if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) {
+      options = new Options();
+      options.https = src.indexOf("https") === 0;
+      if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) {
+        options.host = mm[1];
+        if (mm[2]) {
+          options.port = parseInt(mm[2], 10);
+        }
+      }
+      if (m[2]) {
+        _ref2 = m[2].split('&');
+        for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
+          pair = _ref2[_j];
+          if ((keyAndValue = pair.split('=')).length > 1) {
+            options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('='));
+          }
+        }
+      }
+      return options;
+    }
+  }
+  return null;
+};
+
+// reloader
+// Generated by CoffeeScript 1.3.1
+(function() {
+  var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl;
+
+  splitUrl = function(url) {
+    var hash, index, params;
+    if ((index = url.indexOf('#')) >= 0) {
+      hash = url.slice(index);
+      url = url.slice(0, index);
+    } else {
+      hash = '';
+    }
+    if ((index = url.indexOf('?')) >= 0) {
+      params = url.slice(index);
+      url = url.slice(0, index);
+    } else {
+      params = '';
+    }
+    return {
+      url: url,
+      params: params,
+      hash: hash
+    };
+  };
+
+  pathFromUrl = function(url) {
+    var path;
+    url = splitUrl(url).url;
+    if (url.indexOf('file://') === 0) {
+      path = url.replace(/^file:\/\/(localhost)?/, '');
+    } else {
+      path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/');
+    }
+    return decodeURIComponent(path);
+  };
+
+  pickBestMatch = function(path, objects, pathFunc) {
+    var bestMatch, object, score, _i, _len;
+    bestMatch = {
+      score: 0
+    };
+    for (_i = 0, _len = objects.length; _i < _len; _i++) {
+      object = objects[_i];
+      score = numberOfMatchingSegments(path, pathFunc(object));
+      if (score > bestMatch.score) {
+        bestMatch = {
+          object: object,
+          score: score
+        };
+      }
+    }
+    if (bestMatch.score > 0) {
+      return bestMatch;
+    } else {
+      return null;
+    }
+  };
+
+  numberOfMatchingSegments = function(path1, path2) {
+    var comps1, comps2, eqCount, len;
+    
+    // normalize windows paths
+    path1 = path1.replace(/\\/g,'\/');
+    path2 = path2.replace(/\\/g,'\/');
+    
+    path1 = path1.replace(/^\/+/, '').toLowerCase();
+    path2 = path2.replace(/^\/+/, '').toLowerCase();
+    if (path1 === path2) {
+      return 10000;
+    }
+    comps1 = path1.split('/').reverse();
+    comps2 = path2.split('/').reverse();
+    len = Math.min(comps1.length, comps2.length);
+    eqCount = 0;
+    while (eqCount < len && comps1[eqCount] === comps2[eqCount]) {
+      ++eqCount;
+    }
+    return eqCount;
+  };
+
+  pathsMatch = function(path1, path2) {
+    return numberOfMatchingSegments(path1, path2) > 0;
+  };
+
+  IMAGE_STYLES = [
+    {
+      selector: 'background',
+      styleNames: ['backgroundImage']
+    }, {
+      selector: 'border',
+      styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage']
+    }
+  ];
+
+  __reloader.Reloader = Reloader = (function() {
+
+    Reloader.name = 'Reloader';
+
+    function Reloader(window, console, Timer) {
+      this.window = window;
+      this.console = console;
+      this.Timer = Timer;
+      this.document = this.window.document;
+      this.importCacheWaitPeriod = 200;
+      this.plugins = [];
+    }
+
+    Reloader.prototype.addPlugin = function(plugin) {
+      return this.plugins.push(plugin);
+    };
+
+    Reloader.prototype.analyze = function(callback) {
+      return results;
+    };
+
+    Reloader.prototype.reload = function(path, options) {
+      var plugin, _base, _i, _len, _ref;
+      this.options = options;
+      if ((_base = this.options).stylesheetReloadTimeout == null) {
+        _base.stylesheetReloadTimeout = 15000;
+      }
+      _ref = this.plugins;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        plugin = _ref[_i];
+        if (plugin.reload && plugin.reload(path, options)) {
+          return;
+        }
+      }
+      if (options.liveCSS) {
+        if (path.match(/\.css$/i)) {
+          if (this.reloadStylesheet(path)) {
+            return;
+          }
+        }
+      }
+      if (options.liveImg) {
+        if (path.match(/\.(jpe?g|png|gif)$/i)) {
+          this.reloadImages(path);
+          return;
+        }
+      }
+      return this.reloadPage();
+    };
+
+    Reloader.prototype.reloadPage = function() {
+      return this.window.document.location.reload();
+    };
+
+    Reloader.prototype.reloadImages = function(path) {
+      var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results;
+      expando = this.generateUniqueString();
+      _ref = this.document.images;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        img = _ref[_i];
+        if (pathsMatch(path, pathFromUrl(img.src))) {
+          img.src = this.generateCacheBustUrl(img.src, expando);
+        }
+      }
+      if (this.document.querySelectorAll) {
+        for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) {
+          _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames;
+          _ref2 = this.document.querySelectorAll("[style*=" + selector + "]");
+          for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
+            img = _ref2[_k];
+            this.reloadStyleImages(img.style, styleNames, path, expando);
+          }
+        }
+      }
+      if (this.document.styleSheets) {
+        _ref3 = this.document.styleSheets;
+        _results = [];
+        for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
+          styleSheet = _ref3[_l];
+          _results.push(this.reloadStylesheetImages(styleSheet, path, expando));
+        }
+        return _results;
+      }
+    };
+
+    Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) {
+      var rule, rules, styleNames, _i, _j, _len, _len1;
+      try {
+        rules = styleSheet != null ? styleSheet.cssRules : void 0;
+      } catch (e) {
+
+      }
+      if (!rules) {
+        return;
+      }
+      for (_i = 0, _len = rules.length; _i < _len; _i++) {
+        rule = rules[_i];
+        switch (rule.type) {
+          case CSSRule.IMPORT_RULE:
+            this.reloadStylesheetImages(rule.styleSheet, path, expando);
+            break;
+          case CSSRule.STYLE_RULE:
+            for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) {
+              styleNames = IMAGE_STYLES[_j].styleNames;
+              this.reloadStyleImages(rule.style, styleNames, path, expando);
+            }
+            break;
+          case CSSRule.MEDIA_RULE:
+            this.reloadStylesheetImages(rule, path, expando);
+        }
+      }
+    };
+
+    Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) {
+      var newValue, styleName, value, _i, _len,
+        _this = this;
+      for (_i = 0, _len = styleNames.length; _i < _len; _i++) {
+        styleName = styleNames[_i];
+        value = style[styleName];
+        if (typeof value === 'string') {
+          newValue = value.replace(/\burl\s*\(([^)]*)\)/, function(match, src) {
+            if (pathsMatch(path, pathFromUrl(src))) {
+              return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")";
+            } else {
+              return match;
+            }
+          });
+          if (newValue !== value) {
+            style[styleName] = newValue;
+          }
+        }
+      }
+    };
+
+    Reloader.prototype.reloadStylesheet = function(path) {
+      var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1,
+        _this = this;
+      links = (function() {
+        var _i, _len, _ref, _results;
+        _ref = this.document.getElementsByTagName('link');
+        _results = [];
+        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+          link = _ref[_i];
+          if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) {
+            _results.push(link);
+          }
+        }
+        return _results;
+      }).call(this);
+      imported = [];
+      _ref = this.document.getElementsByTagName('style');
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        style = _ref[_i];
+        if (style.sheet) {
+          this.collectImportedStylesheets(style, style.sheet, imported);
+        }
+      }
+      for (_j = 0, _len1 = links.length; _j < _len1; _j++) {
+        link = links[_j];
+        this.collectImportedStylesheets(link, link.sheet, imported);
+      }
+      if (this.window.StyleFix && this.document.querySelectorAll) {
+        _ref1 = this.document.querySelectorAll('style[data-href]');
+        for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
+          style = _ref1[_k];
+          links.push(style);
+        }
+      }
+      this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets");
+      match = pickBestMatch(path, links.concat(imported), function(l) {
+        return pathFromUrl(_this.linkHref(l));
+      });
+      if (match) {
+        if (match.object.rule) {
+          this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href);
+          this.reattachImportedRule(match.object);
+        } else {
+          this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object)));
+          this.reattachStylesheetLink(match.object);
+        }
+      } else {
+        this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one");
+        for (_l = 0, _len3 = links.length; _l < _len3; _l++) {
+          link = links[_l];
+          this.reattachStylesheetLink(link);
+        }
+      }
+      return true;
+    };
+
+    Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) {
+      var index, rule, rules, _i, _len;
+      try {
+        rules = styleSheet != null ? styleSheet.cssRules : void 0;
+      } catch (e) {
+
+      }
+      if (rules && rules.length) {
+        for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) {
+          rule = rules[index];
+          switch (rule.type) {
+            case CSSRule.CHARSET_RULE:
+              continue;
+            case CSSRule.IMPORT_RULE:
+              result.push({
+                link: link,
+                rule: rule,
+                index: index,
+                href: rule.href
+              });
+              this.collectImportedStylesheets(link, rule.styleSheet, result);
+              break;
+            default:
+              break;
+          }
+        }
+      }
+    };
+
+    Reloader.prototype.waitUntilCssLoads = function(clone, func) {
+      var callbackExecuted, executeCallback, poll,
+        _this = this;
+      callbackExecuted = false;
+      executeCallback = function() {
+        if (callbackExecuted) {
+          return;
+        }
+        callbackExecuted = true;
+        return func();
+      };
+      clone.onload = function() {
+        _this.knownToSupportCssOnLoad = true;
+        return executeCallback();
+      };
+      if (!this.knownToSupportCssOnLoad) {
+        (poll = function() {
+          if (clone.sheet) {
+            return executeCallback();
+          } else {
+            return _this.Timer.start(50, poll);
+          }
+        })();
+      }
+      return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback);
+    };
+
+    Reloader.prototype.linkHref = function(link) {
+      return link.href || link.getAttribute('data-href');
+    };
+
+    Reloader.prototype.reattachStylesheetLink = function(link) {
+      var clone, parent,
+        _this = this;
+      if (link.__LiveReload_pendingRemoval) {
+        return;
+      }
+      link.__LiveReload_pendingRemoval = true;
+      if (link.tagName === 'STYLE') {
+        clone = this.document.createElement('link');
+        clone.rel = 'stylesheet';
+        clone.media = link.media;
+        clone.disabled = link.disabled;
+      } else {
+        clone = link.cloneNode(false);
+      }
+      clone.href = this.generateCacheBustUrl(this.linkHref(link));
+      parent = link.parentNode;
+      if (parent.lastChild === link) {
+        parent.appendChild(clone);
+      } else {
+        parent.insertBefore(clone, link.nextSibling);
+      }
+      return this.waitUntilCssLoads(clone, function() {
+        var additionalWaitingTime;
+        if (/AppleWebKit/.test(navigator.userAgent)) {
+          additionalWaitingTime = 5;
+        } else {
+          additionalWaitingTime = 200;
+        }
+        return _this.Timer.start(additionalWaitingTime, function() {
+          var _ref;
+          if (!link.parentNode) {
+            return;
+          }
+          link.parentNode.removeChild(link);
+          clone.onreadystatechange = null;
+          return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0;
+        });
+      });
+    };
+
+    Reloader.prototype.reattachImportedRule = function(_arg) {
+      var href, index, link, media, newRule, parent, rule, tempLink,
+        _this = this;
+      rule = _arg.rule, index = _arg.index, link = _arg.link;
+      parent = rule.parentStyleSheet;
+      href = this.generateCacheBustUrl(rule.href);
+      media = rule.media.length ? [].join.call(rule.media, ', ') : '';
+      newRule = "@import url(\"" + href + "\") " + media + ";";
+      rule.__LiveReload_newHref = href;
+      tempLink = this.document.createElement("link");
+      tempLink.rel = 'stylesheet';
+      tempLink.href = href;
+      tempLink.__LiveReload_pendingRemoval = true;
+      if (link.parentNode) {
+        link.parentNode.insertBefore(tempLink, link);
+      }
+      return this.Timer.start(this.importCacheWaitPeriod, function() {
+        if (tempLink.parentNode) {
+          tempLink.parentNode.removeChild(tempLink);
+        }
+        if (rule.__LiveReload_newHref !== href) {
+          return;
+        }
+        parent.insertRule(newRule, index);
+        parent.deleteRule(index + 1);
+        rule = parent.cssRules[index];
+        rule.__LiveReload_newHref = href;
+        return _this.Timer.start(_this.importCacheWaitPeriod, function() {
+          if (rule.__LiveReload_newHref !== href) {
+            return;
+          }
+          parent.insertRule(newRule, index);
+          return parent.deleteRule(index + 1);
+        });
+      });
+    };
+
+    Reloader.prototype.generateUniqueString = function() {
+      return 'livereload=' + Date.now();
+    };
+
+    Reloader.prototype.generateCacheBustUrl = function(url, expando) {
+      var hash, oldParams, params, _ref;
+      if (expando == null) {
+        expando = this.generateUniqueString();
+      }
+      _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params;
+      if (this.options.overrideURL) {
+        if (url.indexOf(this.options.serverURL) < 0) {
+          url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url);
+        }
+      }
+      params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) {
+        return "" + sep + expando;
+      });
+      if (params === oldParams) {
+        if (oldParams.length === 0) {
+          params = "?" + expando;
+        } else {
+          params = "" + oldParams + "&" + expando;
+        }
+      }
+      return url + params + hash;
+    };
+
+    return Reloader;
+
+  })();
+
+}).call(this);
+
+// livereload
+var Connector, LiveReload, Options, Reloader, Timer;
+
+Connector = __connector.Connector;
+
+Timer = __timer.Timer;
+
+Options = __options.Options;
+
+Reloader = __reloader.Reloader;
+
+__livereload.LiveReload = LiveReload = (function() {
+
+  function LiveReload(window) {
+    var _this = this;
+    this.window = window;
+    this.listeners = {};
+    this.plugins = [];
+    this.pluginIdentifiers = {};
+    this.console = this.window.location.href.match(/LR-verbose/) && this.window.console && this.window.console.log && this.window.console.error ? this.window.console : {
+      log: function() {},
+      error: function() {}
+    };
+    if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) {
+      console.error("LiveReload disabled because the browser does not seem to support web sockets");
+      return;
+    }
+    if (!(this.options = Options.extract(this.window.document))) {
+      console.error("LiveReload disabled because it could not find its own <SCRIPT> tag");
+      return;
+    }
+    this.reloader = new Reloader(this.window, this.console, Timer);
+    this.connector = new Connector(this.options, this.WebSocket, Timer, {
+      connecting: function() {},
+      socketConnected: function() {},
+      connected: function(protocol) {
+        var _base;
+        if (typeof (_base = _this.listeners).connect === "function") {
+          _base.connect();
+        }
+        _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ").");
+        return _this.analyze();
+      },
+      error: function(e) {
+        if (e instanceof ProtocolError) {
+          return console.log("" + e.message + ".");
+        } else {
+          return console.log("LiveReload internal error: " + e.message);
+        }
+      },
+      disconnected: function(reason, nextDelay) {
+        var _base;
+        if (typeof (_base = _this.listeners).disconnect === "function") {
+          _base.disconnect();
+        }
+        switch (reason) {
+          case 'cannot-connect':
+            return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec.");
+          case 'broken':
+            return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec.");
+          case 'handshake-timeout':
+            return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec.");
+          case 'handshake-failed':
+            return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec.");
+          case 'manual':
+            break;
+          case 'error':
+            break;
+          default:
+            return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec.");
+        }
+      },
+      message: function(message) {
+        switch (message.command) {
+          case 'reload':
+            return _this.performReload(message);
+          case 'alert':
+            return _this.performAlert(message);
+        }
+      }
+    });
+  }
+
+  LiveReload.prototype.on = function(eventName, handler) {
+    return this.listeners[eventName] = handler;
+  };
+
+  LiveReload.prototype.log = function(message) {
+    return this.console.log("" + message);
+  };
+
+  LiveReload.prototype.performReload = function(message) {
+    var _ref, _ref2;
+    this.log("LiveReload received reload request for " + message.path + ".");
+    return this.reloader.reload(message.path, {
+      liveCSS: (_ref = message.liveCSS) != null ? _ref : true,
+      liveImg: (_ref2 = message.liveImg) != null ? _ref2 : true,
+      originalPath: message.originalPath || '',
+      overrideURL: message.overrideURL || '',
+      serverURL: "http://" + this.options.host + ":" + this.options.port
+    });
+  };
+
+  LiveReload.prototype.performAlert = function(message) {
+    return alert(message.message);
+  };
+
+  LiveReload.prototype.shutDown = function() {
+    var _base;
+    this.connector.disconnect();
+    this.log("LiveReload disconnected.");
+    return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0;
+  };
+
+  LiveReload.prototype.hasPlugin = function(identifier) {
+    return !!this.pluginIdentifiers[identifier];
+  };
+
+  LiveReload.prototype.addPlugin = function(pluginClass) {
+    var plugin;
+    var _this = this;
+    if (this.hasPlugin(pluginClass.identifier)) return;
+    this.pluginIdentifiers[pluginClass.identifier] = true;
+    plugin = new pluginClass(this.window, {
+      _livereload: this,
+      _reloader: this.reloader,
+      _connector: this.connector,
+      console: this.console,
+      Timer: Timer,
+      generateCacheBustUrl: function(url) {
+        return _this.reloader.generateCacheBustUrl(url);
+      }
+    });
+    this.plugins.push(plugin);
+    this.reloader.addPlugin(plugin);
+  };
+
+  LiveReload.prototype.analyze = function() {
+    var plugin, pluginData, pluginsData, _i, _len, _ref;
+    if (!(this.connector.protocol >= 7)) return;
+    pluginsData = {};
+    _ref = this.plugins;
+    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+      plugin = _ref[_i];
+      pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {};
+      pluginData.version = plugin.constructor.version;
+    }
+    this.connector.sendCommand({
+      command: 'info',
+      plugins: pluginsData,
+      url: this.window.location.href
+    });
+  };
+
+  return LiveReload;
+
+})();
+
+// less
+var LessPlugin;
+__less = LessPlugin = (function() {
+  LessPlugin.identifier = 'less';
+  LessPlugin.version = '1.0';
+  function LessPlugin(window, host) {
+    this.window = window;
+    this.host = host;
+  }
+  LessPlugin.prototype.reload = function(path, options) {
+    if (this.window.less && this.window.less.refresh) {
+      if (path.match(/\.less$/i)) {
+        return this.reloadLess(path);
+      }
+      if (options.originalPath.match(/\.less$/i)) {
+        return this.reloadLess(options.originalPath);
+      }
+    }
+    return false;
+  };
+  LessPlugin.prototype.reloadLess = function(path) {
+    var link, links, _i, _len;
+    links = (function() {
+      var _i, _len, _ref, _results;
+      _ref = document.getElementsByTagName('link');
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        link = _ref[_i];
+        if (link.href && link.rel === 'stylesheet/less' || (link.rel.match(/stylesheet/) && link.type.match(/^text\/(x-)?less$/))) {
+          _results.push(link);
+        }
+      }
+      return _results;
+    })();
+    if (links.length === 0) {
+      return false;
+    }
+    for (_i = 0, _len = links.length; _i < _len; _i++) {
+      link = links[_i];
+      link.href = this.host.generateCacheBustUrl(link.href);
+    }
+    this.host.console.log("LiveReload is asking LESS to recompile all stylesheets");
+    this.window.less.refresh(true);
+    return true;
+  };
+  LessPlugin.prototype.analyze = function() {
+    return {
+      disable: !!(this.window.less && this.window.less.refresh)
+    };
+  };
+  return LessPlugin;
+})();
+
+// startup
+var CustomEvents, LiveReload, k;
+CustomEvents = __customevents;
+LiveReload = window.LiveReload = new (__livereload.LiveReload)(window);
+for (k in window) {
+  if (k.match(/^LiveReloadPlugin/)) {
+    LiveReload.addPlugin(window[k]);
+  }
+}
+LiveReload.addPlugin(__less);
+LiveReload.on('shutdown', function() {
+  return delete window.LiveReload;
+});
+LiveReload.on('connect', function() {
+  return CustomEvents.fire(document, 'LiveReloadConnect');
+});
+LiveReload.on('disconnect', function() {
+  return CustomEvents.fire(document, 'LiveReloadDisconnect');
+});
+CustomEvents.bind(document, 'LiveReloadShutDown', function() {
+  return LiveReload.shutDown();
+});
+})();
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/server.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/server.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/lib/server.js	(revision 533)
@@ -0,0 +1,208 @@
+var fs        = require('fs');
+var qs        = require('qs');
+var path      = require('path');
+var util      = require('util');
+var http      = require('http');
+var https     = require('https');
+var events    = require('events');
+var parse     = require('url').parse;
+var debug     = require('debug')('tinylr:server');
+var Client    = require('./client');
+var constants = require('constants');
+
+var config = require('../package.json');
+
+function Server(options) {
+  options = this.options = options || {};
+  events.EventEmitter.call(this);
+
+  options.livereload = options.livereload || path.join(__dirname, 'public/livereload.js');
+  options.port = parseInt(options.port || 35729, 10);
+
+  this.on('GET /', this.index.bind(this));
+  this.on('GET /changed', this.changed.bind(this));
+  this.on('POST /changed', this.changed.bind(this));
+  this.on('GET /livereload.js', this.livereload.bind(this));
+  this.on('GET /kill', this.close.bind(this));
+
+  this.clients = {};
+
+  this.configure(options.app);
+}
+
+module.exports = Server;
+
+util.inherits(Server, events.EventEmitter);
+
+Server.prototype.configure = function configure(app) {
+  debug('Configuring %s', app ? 'connect / express application' : 'HTTP server');
+
+  if(!app) {
+    if (this.options.key && this.options.cert) {
+      this.server = https.createServer(this.options, this.handler.bind(this));
+    }
+    else {
+      this.server = http.createServer(this.handler.bind(this));
+    }
+    this.server.on('upgrade', this.websocketify.bind(this));
+    this.server.on('error', this.error.bind(this));
+    return this;
+  }
+
+
+  var self = this;
+  this.app = app;
+
+  this.app.listen = function(port, done) {
+    done = done || function() {};
+    if(port !== self.options.port) {
+      debug('Warn: LiveReload port is not standard (%d). You are listening on %d', self.options.port, port);
+      debug('You\'ll need to rely on the LiveReload snippet');
+      debug('> http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-');
+    }
+
+    var srv = self.server = http.createServer(app);
+    srv.on('upgrade', self.websocketify.bind(self));
+    srv.on('error', self.error.bind(self));
+    srv.on('close', self.close.bind(self));
+    return srv.listen(port, done);
+  };
+
+  return this;
+};
+
+Server.prototype.handler = function handler(req, res, next) {
+  var middleware = typeof next === 'function';
+  debug('LiveReload handler %s (middleware: %s)', req.url, middleware ? 'on' : 'off');
+
+  if(middleware) {
+    if(!req.params && req.query) req.params = req.query;
+    this.handle(req, res, next);
+    return this;
+  }
+
+  req
+    .on('end', this.handle.bind(this, req, res))
+    .on('data', function(chunk) {
+      req.data = req.data || '';
+      req.data += chunk;
+    });
+
+  return this;
+};
+
+Server.prototype.handle = function handle(req, res, next) {
+  var url = parse(req.url);
+  var middleware = typeof next === 'function';
+
+  req.body = {};
+  req.params = {};
+
+  try {
+    req.body = JSON.parse(req.data);
+  } catch(e) {}
+
+  if(url.query) req.params = qs.parse(url.query);
+
+  // todo: parse Accept header
+  res.setHeader('Content-Type', 'application/json');
+
+  // do the routing
+  var route = req.method + ' '  + url.pathname;
+  var respond = this.emit(route, req, res);
+  if(respond) return;
+  if(middleware) return next();
+
+  res.writeHead(404);
+  res.write(JSON.stringify({
+    error: 'not_found',
+    reason: 'no such route'
+  }));
+  res.end();
+};
+
+Server.prototype.websocketify = function websocketify(req, socket, head) {
+  var self = this;
+  var client = new Client(req, socket, head, this.options);
+  this.clients[client.id] = client;
+
+  debug('New LiveReload connection (id: %s)', client.id);
+  client.on('end', function() {
+    debug('Destroy client %s (url: %s)', client.id, client.url);
+    delete self.clients[client.id];
+  });
+};
+
+Server.prototype.listen = function listen(port, fn) {
+  this.port = port;
+  this.server.listen(port, fn);
+};
+
+Server.prototype.close = function close(req, res) {
+  if(res) res.end();
+
+  Object.keys(this.clients).forEach(function(id) {
+    this.clients[id].close();
+  }, this);
+
+  if(this.server._handle) this.server.close(this.emit.bind(this, 'close'));
+};
+
+Server.prototype.error = function error(e) {
+  console.error();
+  console.error('... Uhoh. Got error %s ...', e.message);
+  console.error(e.stack);
+
+  if(e.code !== constants.EADDRINUSE) return;
+  console.error();
+  console.error('You already have a server listening on %s', this.port);
+  console.error('You should stop it and try again.');
+  console.error();
+};
+
+// Routes
+
+Server.prototype.livereload = function livereload(req, res) {
+  fs.createReadStream(this.options.livereload).pipe(res);
+};
+
+Server.prototype.changed = function changed(req, res) {
+  var files = [];
+  if(req && req.body && req.body.files) files = req.body.files;
+  if(req && req.params && req.params.files) files = req.params.files;
+
+  // normalize files array
+  files = Array.isArray(files) ? files :
+    typeof files === 'string' ? files.split(/[\s,]/) :
+    [];
+
+
+  debug('Changed event (Files: %s)', files.join(' '));
+  var clients = Object.keys(this.clients).map(function(id) {
+    var client = this.clients[id];
+    debug('Reloading client %s (url: %s)', client.id, client.url);
+    client.reload(files);
+    return {
+      id: client.id,
+      url: client.url
+    };
+  }, this);
+
+  if(!res) return;
+
+  res.write(JSON.stringify({
+    clients: clients,
+    files: files
+  }));
+
+  res.end();
+};
+
+Server.prototype.index = function index(req, res) {
+  res.write(JSON.stringify({
+    tinylr: 'Welcome',
+    version: config.version
+  }));
+
+  res.end();
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/Readme.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/Readme.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/Readme.md	(revision 533)
@@ -0,0 +1,115 @@
+# debug
+
+  tiny node.js debugging utility modelled after node core's debugging technique.
+
+## Installation
+
+```
+$ npm install debug
+```
+
+## Usage
+
+ With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
+ 
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stderr is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+  _(NOTE: Debug now uses stderr instead of stdout, so the correct shell command for this example is actually `DEBUG=* node example/worker 2> out &`)_
+  
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+  
+## Conventions
+
+ If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". 
+
+## Wildcards
+
+  The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:".
+
+## Browser support
+
+ Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. 
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  a('doing some work');
+}, 1200);
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/debug.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/debug.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/debug.js	(revision 533)
@@ -0,0 +1,137 @@
+
+/**
+ * Expose `debug()` as the module.
+ */
+
+module.exports = debug;
+
+/**
+ * Create a debugger with the given `name`.
+ *
+ * @param {String} name
+ * @return {Type}
+ * @api public
+ */
+
+function debug(name) {
+  if (!debug.enabled(name)) return function(){};
+
+  return function(fmt){
+    fmt = coerce(fmt);
+
+    var curr = new Date;
+    var ms = curr - (debug[name] || curr);
+    debug[name] = curr;
+
+    fmt = name
+      + ' '
+      + fmt
+      + ' +' + debug.humanize(ms);
+
+    // This hackery is required for IE8
+    // where `console.log` doesn't have 'apply'
+    window.console
+      && console.log
+      && Function.prototype.apply.call(console.log, console, arguments);
+  }
+}
+
+/**
+ * The currently active debug mode names.
+ */
+
+debug.names = [];
+debug.skips = [];
+
+/**
+ * Enables a debug mode by name. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} name
+ * @api public
+ */
+
+debug.enable = function(name) {
+  try {
+    localStorage.debug = name;
+  } catch(e){}
+
+  var split = (name || '').split(/[\s,]+/)
+    , len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    name = split[i].replace('*', '.*?');
+    if (name[0] === '-') {
+      debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
+    }
+    else {
+      debug.names.push(new RegExp('^' + name + '$'));
+    }
+  }
+};
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+debug.disable = function(){
+  debug.enable('');
+};
+
+/**
+ * Humanize the given `ms`.
+ *
+ * @param {Number} m
+ * @return {String}
+ * @api private
+ */
+
+debug.humanize = function(ms) {
+  var sec = 1000
+    , min = 60 * 1000
+    , hour = 60 * min;
+
+  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
+  if (ms >= min) return (ms / min).toFixed(1) + 'm';
+  if (ms >= sec) return (ms / sec | 0) + 's';
+  return ms + 'ms';
+};
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+debug.enabled = function(name) {
+  for (var i = 0, len = debug.skips.length; i < len; i++) {
+    if (debug.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (var i = 0, len = debug.names.length; i < len; i++) {
+    if (debug.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+};
+
+/**
+ * Coerce `val`.
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
+
+// persist
+
+try {
+  if (window.localStorage) debug.enable(localStorage.debug);
+} catch(e){}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/index.js	(revision 533)
@@ -0,0 +1,5 @@
+if ('undefined' == typeof window) {
+  module.exports = require('./lib/debug');
+} else {
+  module.exports = require('./debug');
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/lib/debug.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/lib/debug.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/lib/debug.js	(revision 533)
@@ -0,0 +1,147 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+
+/**
+ * Expose `debug()` as the module.
+ */
+
+module.exports = debug;
+
+/**
+ * Enabled debuggers.
+ */
+
+var names = []
+  , skips = [];
+
+(process.env.DEBUG || '')
+  .split(/[\s,]+/)
+  .forEach(function(name){
+    name = name.replace('*', '.*?');
+    if (name[0] === '-') {
+      skips.push(new RegExp('^' + name.substr(1) + '$'));
+    } else {
+      names.push(new RegExp('^' + name + '$'));
+    }
+  });
+
+/**
+ * Colors.
+ */
+
+var colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Previous debug() call.
+ */
+
+var prev = {};
+
+/**
+ * Previously assigned color.
+ */
+
+var prevColor = 0;
+
+/**
+ * Is stdout a TTY? Colored output is disabled when `true`.
+ */
+
+var isatty = tty.isatty(2);
+
+/**
+ * Select a color.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+function color() {
+  return colors[prevColor++ % colors.length];
+}
+
+/**
+ * Humanize the given `ms`.
+ *
+ * @param {Number} m
+ * @return {String}
+ * @api private
+ */
+
+function humanize(ms) {
+  var sec = 1000
+    , min = 60 * 1000
+    , hour = 60 * min;
+
+  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
+  if (ms >= min) return (ms / min).toFixed(1) + 'm';
+  if (ms >= sec) return (ms / sec | 0) + 's';
+  return ms + 'ms';
+}
+
+/**
+ * Create a debugger with the given `name`.
+ *
+ * @param {String} name
+ * @return {Type}
+ * @api public
+ */
+
+function debug(name) {
+  function disabled(){}
+  disabled.enabled = false;
+
+  var match = skips.some(function(re){
+    return re.test(name);
+  });
+
+  if (match) return disabled;
+
+  match = names.some(function(re){
+    return re.test(name);
+  });
+
+  if (!match) return disabled;
+  var c = color();
+
+  function colored(fmt) {
+    fmt = coerce(fmt);
+
+    var curr = new Date;
+    var ms = curr - (prev[name] || curr);
+    prev[name] = curr;
+
+    fmt = '  \u001b[9' + c + 'm' + name + ' '
+      + '\u001b[3' + c + 'm\u001b[90m'
+      + fmt + '\u001b[3' + c + 'm'
+      + ' +' + humanize(ms) + '\u001b[0m';
+
+    console.error.apply(this, arguments);
+  }
+
+  function plain(fmt) {
+    fmt = coerce(fmt);
+
+    fmt = new Date().toUTCString()
+      + ' ' + name + ' ' + fmt;
+    console.error.apply(this, arguments);
+  }
+
+  colored.enabled = plain.enabled = true;
+
+  return isatty || process.env.DEBUG_COLORS
+    ? colored
+    : plain;
+}
+
+/**
+ * Coerce `val`.
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/debug/package.json	(revision 533)
@@ -0,0 +1,46 @@
+{
+  "name": "debug",
+  "version": "0.7.4",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "description": "small debugging utility",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "main": "lib/debug.js",
+  "browser": "./debug.js",
+  "engines": {
+    "node": "*"
+  },
+  "files": [
+    "lib/debug.js",
+    "debug.js",
+    "index.js"
+  ],
+  "component": {
+    "scripts": {
+      "debug/index.js": "index.js",
+      "debug/debug.js": "debug.js"
+    }
+  },
+  "readme": "# debug\n\n  tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n  , http = require('http')\n  , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n  debug(req.method + ' ' + req.url);\n  res.end('hello\\n');\n}).listen(3000, function(){\n  debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n  debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n  When stderr is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n  _(NOTE: Debug now uses stderr instead of stdout, so the correct shell command for this example is actually `DEBUG=* node example/worker 2> out &`)_\n  \n  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n  \n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n  The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n  You can also exclude specific debuggers by prefixing them with a \"-\" character.  For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n  a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n  a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "homepage": "https://github.com/visionmedia/debug",
+  "_id": "debug@0.7.4",
+  "_from": "debug@~0.7.0"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/CHANGELOG.txt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/CHANGELOG.txt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/CHANGELOG.txt	(revision 533)
@@ -0,0 +1,62 @@
+=== 0.4.4 / 2013-02-14
+
+* Emit the 'close' event if TCP is closed before CLOSE frame is acked
+
+
+=== 0.4.3 / 2012-07-09
+
+* Add 'Connection: close' to EventSource response
+* Handle situations where request.socket is undefined
+
+
+=== 0.4.2 / 2012-04-06
+
+* Add WebSocket error code 1011.
+* Handle URLs with no path correctly by sending 'GET /'
+
+
+=== 0.4.1 / 2012-02-26
+
+* Treat anything other than a Buffer as a string when calling send()
+
+
+=== 0.4.0 / 2012-02-13
+
+* Add ping() method to server-side WebSocket and EventSource
+* Buffer send() calls until the draft-76 handshake is complete
+* Fix HTTPS problems on Node 0.7
+
+
+=== 0.3.1 / 2012-01-16
+
+* Call setNoDelay(true) on net.Socket objects to reduce latency
+
+
+=== 0.3.0 / 2012-01-13
+
+* Add support for EventSource connections
+
+
+=== 0.2.0 / 2011-12-21
+
+* Add support for Sec-WebSocket-Protocol negotiation
+* Support hixie-76 close frames and 75/76 ignored segments
+* Improve performance of HyBi parsing/framing functions
+* Decouple parsers from TCP and reduce write volume
+
+
+=== 0.1.2 / 2011-12-05
+
+* Detect closed sockets on the server side when TCP connection breaks
+* Make hixie-76 sockets work through HAProxy
+
+
+=== 0.1.1 / 2011-11-30
+
+* Fix addEventListener() interface methods
+
+
+=== 0.1.0 / 2011-11-27
+
+* Initial release, based on WebSocket components from Faye
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/README.markdown
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/README.markdown	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/README.markdown	(revision 533)
@@ -0,0 +1,248 @@
+# faye-websocket
+
+* Travis CI build: [<img src="https://secure.travis-ci.org/faye/faye-websocket-node.png" />](http://travis-ci.org/faye/faye-websocket-node)
+* Autobahn tests: [server](http://faye.jcoglan.com/autobahn/servers/), [client](http://faye.jcoglan.com/autobahn/clients/)
+
+This is a robust, general-purpose WebSocket implementation extracted from the
+[Faye](http://faye.jcoglan.com) project. It provides classes for easily building
+WebSocket servers and clients in Node. It does not provide a server itself, but
+rather makes it easy to handle WebSocket connections within an existing
+[Node](http://nodejs.org/) application. It does not provide any abstraction
+other than the standard [WebSocket API](http://dev.w3.org/html5/websockets/).
+
+It also provides an abstraction for handling [EventSource](http://dev.w3.org/html5/eventsource/)
+connections, which are one-way connections that allow the server to push data to
+the client. They are based on streaming HTTP responses and can be easier to
+access via proxies than WebSockets.
+
+The server-side socket can process [draft-75](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75),
+[draft-76](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76),
+[hybi-07](http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07)
+and later versions of the protocol. It selects protocol versions automatically,
+supports both `text` and `binary` messages, and transparently handles `ping`,
+`pong`, `close` and fragmented messages.
+
+
+## Handling WebSocket connections in Node
+
+You can handle WebSockets on the server side by listening for HTTP Upgrade
+requests, and creating a new socket for the request. This socket object exposes
+the usual WebSocket methods for receiving and sending messages. For example this
+is how you'd implement an echo server:
+
+```js
+var WebSocket = require('faye-websocket'),
+    http      = require('http');
+
+var server = http.createServer();
+
+server.addListener('upgrade', function(request, socket, head) {
+  var ws = new WebSocket(request, socket, head);
+  
+  ws.onmessage = function(event) {
+    ws.send(event.data);
+  };
+  
+  ws.onclose = function(event) {
+    console.log('close', event.code, event.reason);
+    ws = null;
+  };
+});
+
+server.listen(8000);
+```
+
+Note that under certain circumstances (notably a draft-76 client connecting
+through an HTTP proxy), the WebSocket handshake will not be complete after you
+call `new WebSocket()` because the server will not have received the entire
+handshake from the client yet. In this case, calls to `ws.send()` will buffer
+the message in memory until the handshake is complete, at which point any
+buffered messages will be sent to the client.
+
+If you need to detect when the WebSocket handshake is complete, you can use the
+`onopen` event.
+
+If the connection's protocol version supports it, you can call `ws.ping()` to
+send a ping message and wait for the client's response. This method takes a
+message string, and an optional callback that fires when a matching pong message
+is received. It returns `true` iff a ping message was sent. If the client does
+not support ping/pong, this method sends no data and returns `false`.
+
+```js
+ws.ping('Mic check, one, two', function() {
+  // fires when pong is received
+});
+```
+
+
+## Using the WebSocket client
+
+The client supports both the plain-text `ws` protocol and the encrypted `wss`
+protocol, and has exactly the same interface as a socket you would use in a web
+browser. On the wire it identifies itself as hybi-13.
+
+```js
+var WebSocket = require('faye-websocket'),
+    ws        = new WebSocket.Client('ws://www.example.com/');
+
+ws.onopen = function(event) {
+  console.log('open');
+  ws.send('Hello, world!');
+};
+
+ws.onmessage = function(event) {
+  console.log('message', event.data);
+};
+
+ws.onclose = function(event) {
+  console.log('close', event.code, event.reason);
+  ws = null;
+};
+```
+
+
+## Subprotocol negotiation
+
+The WebSocket protocol allows peers to select and identify the application
+protocol to use over the connection. On the client side, you can set which
+protocols the client accepts by passing a list of protocol names when you
+construct the socket:
+
+```js
+var ws = new WebSocket.Client('ws://www.example.com/', ['irc', 'amqp']);
+```
+
+On the server side, you can likewise pass in the list of protocols the server
+supports after the other constructor arguments:
+
+```js
+var ws = new WebSocket(request, socket, head, ['irc', 'amqp']);
+```
+
+If the client and server agree on a protocol, both the client- and server-side
+socket objects expose the selected protocol through the `ws.protocol` property.
+If they cannot agree on a protocol to use, the client closes the connection.
+
+
+## WebSocket API
+
+The WebSocket API consists of several event handlers and a method for sending
+messages.
+
+* <b><tt>onopen</tt></b> fires when the socket connection is established. Event
+  has no attributes.
+* <b><tt>onerror</tt></b> fires when the connection attempt fails. Event has no
+  attributes.
+* <b><tt>onmessage</tt></b> fires when the socket receives a message. Event has
+  one attribute, <b><tt>data</tt></b>, which is either a `String` (for text
+  frames) or a `Buffer` (for binary frames).
+* <b><tt>onclose</tt></b> fires when either the client or the server closes the
+  connection. Event has two optional attributes, <b><tt>code</tt></b> and
+  <b><tt>reason</tt></b>, that expose the status code and message sent by the
+  peer that closed the connection.
+* <b><tt>send(message)</tt></b> accepts either a `String` or a `Buffer` and
+  sends a text or binary message over the connection to the other peer.
+* <b><tt>close(code, reason)</tt></b> closes the connection, sending the given
+  status code and reason text, both of which are optional.
+* <b><tt>protocol</tt></b> is a string (which may be empty) identifying the
+  subprotocol the socket is using.
+
+
+## Handling EventSource connections in Node
+
+EventSource connections provide a very similar interface, although because they
+only allow the server to send data to the client, there is no `onmessage` API.
+EventSource allows the server to push text messages to the client, where each
+message has an optional event-type and ID.
+
+```js
+var WebSocket   = require('faye-websocket'),
+    EventSource = WebSocket.EventSource,
+    http        = require('http');
+
+var server = http.createServer();
+
+server.addListener('request', function(request, response) {
+  if (EventSource.isEventSource(request)) {
+    var es = new EventSource(request, response);
+    console.log('open', es.url, es.lastEventId);
+    
+    // Periodically send messages
+    var loop = setInterval(function() { es.send('Hello') }, 1000);
+    
+    es.onclose = function() {
+      clearInterval(loop);
+      es = null;
+    };
+  
+  } else {
+    // Normal HTTP request
+    response.writeHead(200, {'Content-Type': 'text/plain'});
+    response.write('Hello');
+    response.end();
+  }
+});
+
+server.listen(8000);
+```
+
+The `send` method takes two optional parameters, `event` and `id`. The default
+event-type is `'message'` with no ID. For example, to send a `notification`
+event with ID `99`:
+
+```js
+es.send('Breaking News!', {event: 'notification', id: '99'});
+```
+
+The `EventSource` object exposes the following properties:
+
+* <b><tt>url</tt></b> is a string containing the URL the client used to create
+  the EventSource.
+* <b><tt>lastEventId</tt></b> is a string containing the last event ID
+  received by the client. You can use this when the client reconnects after a
+  dropped connection to determine which messages need resending.
+
+When you initialize an EventSource with ` new EventSource()`, you can pass
+configuration options after the `response` parameter. Available options are:
+
+* <b><tt>retry</tt></b> is a number that tells the client how long (in seconds)
+  it should wait after a dropped connection before attempting to reconnect.
+* <b><tt>ping</tt></b> is a number that tells the server how often (in seconds)
+  to send 'ping' packets to the client to keep the connection open, to defeat
+  timeouts set by proxies. The client will ignore these messages.
+
+For example, this creates a connection that pings every 15 seconds and is
+retryable every 10 seconds if the connection is broken:
+
+```js
+var es = new EventSource(request, response, {ping: 15, retry: 10});
+```
+
+You can send a ping message at any time by calling `es.ping()`. Unlike WebSocket,
+the client does not send a response to this; it is merely to send some data over
+the wire to keep the connection alive.
+
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2009-2013 James Coglan
+
+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.
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/autobahn_client.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/autobahn_client.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/autobahn_client.js	(revision 533)
@@ -0,0 +1,44 @@
+var WebSocket = require('../lib/faye/websocket'),
+    pace      = require('pace');
+
+var host  = 'ws://localhost:9001',
+    agent = 'Node ' + process.version,
+    cases = 0,
+    skip  = [];
+
+var socket = new WebSocket.Client(host + '/getCaseCount'),
+    progress;
+
+socket.onmessage = function(event) {
+  console.log('Total cases to run: ' + event.data);
+  cases = parseInt(event.data);
+  progress = pace(cases);
+};
+
+socket.onclose = function() {
+  var runCase = function(n) {
+    progress.op();
+
+    if (n > cases) {
+      socket = new WebSocket.Client(host + '/updateReports?agent=' + encodeURIComponent(agent));
+      socket.onclose = process.exit;
+
+    } else if (skip.indexOf(n) >= 0) {
+      runCase(n + 1);
+
+    } else {
+      socket = new WebSocket.Client(host + '/runCase?case=' + n + '&agent=' + encodeURIComponent(agent));
+
+      socket.onmessage = function(event) {
+        socket.send(event.data);
+      };
+
+      socket.onclose = function() {
+        runCase(n + 1);
+      };
+    }
+  };
+
+  runCase(1);
+};
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/client.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/client.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/client.js	(revision 533)
@@ -0,0 +1,22 @@
+var WebSocket = require('../lib/faye/websocket'),
+    port      = process.argv[2] || 7000,
+    secure    = process.argv[3] === 'ssl',
+    scheme    = secure ? 'wss' : 'ws',
+    ws        = new WebSocket.Client(scheme + '://localhost:' + port + '/');
+
+console.log('Connecting to ' + ws.url);
+
+ws.onopen = function(event) {
+  console.log('open');
+  ws.send('Hello, WebSocket!');
+};
+
+ws.onmessage = function(event) {
+  console.log('message', event.data);
+  // ws.close(1002, 'Going away');
+};
+
+ws.onclose = function(event) {
+  console.log('close', event.code, event.reason);
+};
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/haproxy.conf
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/haproxy.conf	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/haproxy.conf	(revision 533)
@@ -0,0 +1,21 @@
+defaults
+   mode http
+   timeout client  5s
+   timeout connect 5s
+   timeout server  5s
+
+frontend all 0.0.0.0:3000
+   mode http
+   timeout client 120s
+
+   option forwardfor
+   option http-server-close
+   option http-pretend-keepalive
+
+   default_backend sockets
+
+backend sockets
+   balance uri depth 2
+   timeout server  120s
+   server socket1 127.0.0.1:7000
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/server.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/server.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/server.js	(revision 533)
@@ -0,0 +1,70 @@
+var WebSocket = require('../lib/faye/websocket'),
+    fs        = require('fs'),
+    http      = require('http'),
+    https     = require('https');
+
+var port   = process.argv[2] || 7000,
+    secure = process.argv[3] === 'ssl';
+
+var upgradeHandler = function(request, socket, head) {
+  var ws = new WebSocket(request, socket, head, ['irc', 'xmpp'], {ping: 5});
+  console.log('open', ws.url, ws.version, ws.protocol);
+
+  ws.onmessage = function(event) {
+    ws.send(event.data);
+  };
+
+  ws.onclose = function(event) {
+    console.log('close', event.code, event.reason);
+    ws = null;
+  };
+};
+
+var requestHandler = function(request, response) {
+  if (!WebSocket.EventSource.isEventSource(request))
+    return staticHandler(request, response);
+
+  var es   = new WebSocket.EventSource(request, response),
+      time = parseInt(es.lastEventId, 10) || 0;
+
+  console.log('open', es.url, es.lastEventId);
+
+  var loop = setInterval(function() {
+    time += 1;
+    es.send('Time: ' + time);
+    setTimeout(function() {
+      if (es) es.send('Update!!', {event: 'update', id: time});
+    }, 1000);
+  }, 2000);
+
+  es.send('Welcome!\n\nThis is an EventSource server.');
+
+  es.onclose = function() {
+    clearInterval(loop);
+    console.log('close', es.url);
+    es = null;
+  };
+};
+
+var staticHandler = function(request, response) {
+  var path = request.url;
+
+  fs.readFile(__dirname + path, function(err, content) {
+    var status = err ? 404 : 200;
+    response.writeHead(status, {'Content-Type': 'text/html'});
+    response.write(content || 'Not found');
+    response.end();
+  });
+};
+
+var server = secure
+           ? https.createServer({
+               key:  fs.readFileSync(__dirname + '/../spec/server.key'),
+               cert: fs.readFileSync(__dirname + '/../spec/server.crt')
+             })
+           : http.createServer();
+
+server.addListener('request', requestHandler);
+server.addListener('upgrade', upgradeHandler);
+server.listen(port);
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/sse.html
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/sse.html	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/sse.html	(revision 533)
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+  <head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+    <title>EventSource test</title>
+  </head>
+  <body>
+
+    <h1>EventSource test</h1>
+    <ul></ul>
+
+    <script type="text/javascript">
+      var logger = document.getElementsByTagName('ul')[0],
+          socket = new EventSource('/');
+
+      var log = function(text) {
+        logger.innerHTML += '<li>' + text + '</li>';
+      };
+
+      socket.onopen = function() {
+        log('OPEN');
+      };
+
+      socket.onmessage = function(event) {
+        log('MESSAGE: ' + event.data);
+      };
+
+      socket.addEventListener('update', function(event) {
+        log('UPDATE(' + event.lastEventId + '): ' + event.data);
+      });
+
+      socket.onerror = function(event) {
+        log('ERROR: ' + event.message);
+      };
+    </script>
+
+  </body>
+</html>
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/ws.html
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/ws.html	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/examples/ws.html	(revision 533)
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+  <head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+    <title>WebSocket test</title>
+  </head>
+  <body>
+
+    <h1>WebSocket test</h1>
+    <ul></ul>
+
+    <script type="text/javascript">
+      var logger = document.getElementsByTagName('ul')[0],
+          Socket = window.MozWebSocket || window.WebSocket,
+          protos = ['foo', 'bar', 'xmpp'],
+          socket = new Socket('ws://' + location.hostname + ':' + location.port + '/', protos),
+          index  = 0;
+
+      var log = function(text) {
+        logger.innerHTML += '<li>' + text + '</li>';
+      };
+
+      socket.addEventListener('open', function() {
+        log('OPEN: ' + socket.protocol);
+        socket.send('Hello, world');
+      });
+
+      socket.onerror = function(event) {
+        log('ERROR: ' + event.message);
+      };
+
+      socket.onmessage = function(event) {
+        log('MESSAGE: ' + event.data);
+        setTimeout(function() { socket.send(++index + ' ' + event.data) }, 2000);
+      };
+
+      socket.onclose = function(event) {
+        log('CLOSE: ' + event.code + ', ' + event.reason);
+      };
+    </script>
+
+  </body>
+</html>
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/eventsource.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/eventsource.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/eventsource.js	(revision 533)
@@ -0,0 +1,110 @@
+var API   = require('./websocket/api'),
+    Event = require('./websocket/api/event');
+
+var isSecureConnection = function(request) {
+  if (request.headers['x-forwarded-proto']) {
+    return request.headers['x-forwarded-proto'] === 'https';
+  } else {
+    return (request.connection && request.connection.authorized !== undefined) ||
+           (request.socket && request.socket.secure);
+  }
+};
+
+var EventSource = function(request, response, options) {
+  options = options || {};
+
+  this._request  = request;
+  this._response = response;
+  this._stream   = response.socket;
+  this._ping     = options.ping  || this.DEFAULT_PING;
+  this._retry    = options.retry || this.DEFAULT_RETRY;
+
+  var scheme = isSecureConnection(request) ? 'https:' : 'http:';
+  this.url = scheme + '//' + request.headers.host + request.url;
+
+  this.lastEventId = request.headers['last-event-id'] || '';
+
+  var self = this;
+  this.readyState = API.CONNECTING;
+  this._sendBuffer = [];
+  process.nextTick(function() { self._open() });
+
+  var handshake = 'HTTP/1.1 200 OK\r\n' +
+                  'Content-Type: text/event-stream\r\n' +
+                  'Cache-Control: no-cache, no-store\r\n' +
+                  'Connection: close\r\n' +
+                  '\r\n\r\n' +
+                  'retry: ' + Math.floor(this._retry * 1000) + '\r\n\r\n';
+
+  this.readyState = API.OPEN;
+
+  if (this._ping)
+    this._pingLoop = setInterval(function() { self.ping() }, this._ping * 1000);
+
+  if (!this._stream || !this._stream.writable) return;
+
+  this._stream.setTimeout(0);
+  this._stream.setNoDelay(true);
+
+  try { this._stream.write(handshake, 'utf8') } catch (e) {}
+
+  ['close', 'end', 'error'].forEach(function(event) {
+    self._stream.addListener(event, function() { self.close() });
+  });
+};
+
+EventSource.isEventSource = function(request) {
+  var accept = (request.headers.accept || '').split(/\s*,\s*/);
+  return accept.indexOf('text/event-stream') >= 0;
+};
+
+var instance = {
+  DEFAULT_PING:   10,
+  DEFAULT_RETRY:  5,
+
+  send: function(message, options) {
+    if (this.readyState !== API.OPEN) return false;
+
+    message = String(message).replace(/(\r\n|\r|\n)/g, '$1data: ');
+    options = options || {};
+
+    var frame = '';
+    if (options.event) frame += 'event: ' + options.event + '\r\n';
+    if (options.id)    frame += 'id: '    + options.id    + '\r\n';
+    frame += 'data: ' + message + '\r\n\r\n';
+
+    try {
+      this._stream.write(frame, 'utf8');
+      return true;
+    } catch (e) {
+      return false;
+    }
+  },
+
+  ping: function() {
+    try {
+      this._stream.write(':\r\n\r\n', 'utf8');
+      return true;
+    } catch (e) {
+      return false;
+    }
+  },
+
+  close: function() {
+    if (this.readyState === API.CLOSING || this.readyState === API.CLOSED)
+      return;
+
+    this.readyState = API.CLOSED;
+    clearInterval(this._pingLoop);
+    this._response.end();
+
+    var event = new Event('close');
+    event.initEvent('close', false, false);
+    this.dispatchEvent(event);
+  }
+};
+
+for (var key in API) EventSource.prototype[key] = API[key];
+for (var key in instance) EventSource.prototype[key] = instance[key];
+module.exports = EventSource;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket.js	(revision 533)
@@ -0,0 +1,93 @@
+// API and protocol references:
+// 
+// * http://dev.w3.org/html5/websockets/
+// * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget
+// * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-event
+// * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75
+// * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
+// * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+
+var Draft75Parser = require('./websocket/draft75_parser'),
+    Draft76Parser = require('./websocket/draft76_parser'),
+    HybiParser    = require('./websocket/hybi_parser'),
+    API           = require('./websocket/api'),
+    Event         = require('./websocket/api/event');
+
+var getParser = function(request) {
+  var headers = request.headers;
+  return headers['sec-websocket-version']
+       ? HybiParser
+       : (headers['sec-websocket-key1'] && headers['sec-websocket-key2'])
+       ? Draft76Parser
+       : Draft75Parser;
+};
+
+var isSecureConnection = function(request) {
+  if (request.headers['x-forwarded-proto']) {
+    return request.headers['x-forwarded-proto'] === 'https';
+  } else {
+    return (request.connection && request.connection.authorized !== undefined) ||
+           (request.socket && request.socket.secure);
+  }
+};
+
+var WebSocket = function(request, socket, head, supportedProtos, options) {
+  this.request = request;
+  this._stream = request.socket;
+  this._ping   = options && options.ping;
+  this._pingId = 0;
+
+  var scheme = isSecureConnection(request) ? 'wss:' : 'ws:';
+  this.url = scheme + '//' + request.headers.host + request.url;
+  this.readyState = API.CONNECTING;
+  this.bufferedAmount = 0;
+
+  var Parser = getParser(request);
+  this._parser = new Parser(this, {protocols: supportedProtos});
+
+  var self = this;
+  this._sendBuffer = [];
+  process.nextTick(function() { self._open() });
+
+  var handshake = this._parser.handshakeResponse(head);
+  if (this._parser.isOpen()) this.readyState = API.OPEN;
+
+  if (this._ping)
+    this._pingLoop = setInterval(function() {
+      self._pingId += 1;
+      self.ping(self._pingId.toString());
+    }, this._ping * 1000);
+
+  this.protocol = this._parser.protocol || '';
+  this.version = this._parser.getVersion();
+
+  if (!this._stream || !this._stream.writable) return;
+
+  this._stream.setTimeout(0);
+  this._stream.setNoDelay(true);
+
+  try { this._stream.write(handshake, 'binary') } catch (e) {}
+
+  this._stream.addListener('data', function(data) {
+    var response = self._parser.parse(data);
+    if (!response) return;
+    try { self._stream.write(response, 'binary') } catch (e) {}
+    self._open();
+  });
+  ['close', 'end', 'error'].forEach(function(event) {
+    self._stream.addListener(event, function() { self.close(1006, '', false) });
+  });
+};
+
+WebSocket.prototype.ping = function(message, callback, context) {
+  if (!this._parser.ping) return false;
+  return this._parser.ping(message, callback, context);
+};
+
+for (var key in API) WebSocket.prototype[key] = API[key];
+
+WebSocket.WebSocket   = WebSocket;
+WebSocket.Client      = require('./websocket/client');
+WebSocket.EventSource = require('./eventsource');
+module.exports        = WebSocket;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api.js	(revision 533)
@@ -0,0 +1,88 @@
+var EventTarget = require('./api/event_target'),
+    Event       = require('./api/event');
+
+var API = {
+  CONNECTING:   0,
+  OPEN:         1,
+  CLOSING:      2,
+  CLOSED:       3,
+
+  _open: function() {
+    if (this._parser && !this._parser.isOpen()) return;
+    this.readyState = API.OPEN;
+
+    var buffer = this._sendBuffer || [],
+        message;
+
+    while (message = buffer.shift())
+      this.send.apply(this, message);
+
+    var event = new Event('open');
+    event.initEvent('open', false, false);
+    this.dispatchEvent(event);
+  },
+
+  receive: function(data) {
+    if (this.readyState !== API.OPEN) return false;
+    var event = new Event('message');
+    event.initEvent('message', false, false);
+    event.data = data;
+    this.dispatchEvent(event);
+  },
+
+  send: function(data, type, errorType) {
+    if (this.readyState === API.CONNECTING) {
+      if (this._sendBuffer) {
+        this._sendBuffer.push(arguments);
+        return true;
+      } else {
+        throw new Error('Cannot call send(), socket is not open yet');
+      }
+    }
+
+    if (this.readyState === API.CLOSED)
+      return false;
+
+    if (!(data instanceof Buffer)) data = String(data);
+
+    var frame = this._parser.frame(data, type, errorType);
+    try {
+      this._stream.write(frame, 'binary');
+      return true;
+    } catch (e) {
+      return false;
+    }
+  },
+
+  close: function(code, reason, ack) {
+    if (this.readyState === API.CLOSED) return;
+    if (this.readyState === API.CLOSING && ack !== false) return;
+
+    var finalize = function() {
+      this.readyState = API.CLOSED;
+      if (this._pingLoop) clearInterval(this._pingLoop);
+      if (this._stream) this._stream.end();
+      var event = new Event('close', {code: code || 1000, reason: reason || ''});
+      event.initEvent('close', false, false);
+      this.dispatchEvent(event);
+    };
+
+    if (this.readyState === API.CONNECTING)
+      return finalize.call(this);
+
+    this.readyState = API.CLOSING;
+
+    if (ack === false) {
+      if (this._parser.close) this._parser.close(code, reason);
+      finalize.call(this);
+    } else {
+      if (this._parser.close) this._parser.close(code, reason, finalize, this);
+      else finalize.call(this);
+    }
+  }
+};
+
+for (var key in EventTarget) API[key] = EventTarget[key];
+
+module.exports = API;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api/event.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api/event.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api/event.js	(revision 533)
@@ -0,0 +1,21 @@
+var Event = function(eventType, options) {
+  this.type = eventType;
+  for (var key in options)
+    this[key] = options[key];
+};
+
+Event.prototype.initEvent = function(eventType, canBubble, cancelable) {
+  this.type       = eventType;
+  this.bubbles    = canBubble;
+  this.cancelable = cancelable;
+};
+
+Event.prototype.stopPropagation = function() {};
+Event.prototype.preventDefault  = function() {};
+
+Event.CAPTURING_PHASE = 1;
+Event.AT_TARGET       = 2;
+Event.BUBBLING_PHASE  = 3;
+
+module.exports = Event;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js	(revision 533)
@@ -0,0 +1,47 @@
+var Event = require('./event');
+
+var EventTarget = {
+  onopen:     null,
+  onmessage:  null,
+  onerror:    null,
+  onclose:    null,
+
+  addEventListener: function(eventType, listener, useCapture) {
+    this._listeners = this._listeners || {};
+    var list = this._listeners[eventType] = this._listeners[eventType] || [];
+    list.push(listener);
+  },
+
+  removeEventListener: function(eventType, listener, useCapture) {
+    if (!this._listeners || !this._listeners[eventType]) return;
+
+    if (!listener) {
+      delete this._listeners[eventType];
+      return;
+    }
+    var list = this._listeners[eventType],
+        i    = list.length;
+
+    while (i--) {
+      if (listener !== list[i]) continue;
+      list.splice(i,1);
+    }
+  },
+
+  dispatchEvent: function(event) {
+    event.target = event.currentTarget = this;
+    event.eventPhase = Event.AT_TARGET;
+
+    if (this['on' + event.type])
+      this['on' + event.type](event);
+
+    if (!this._listeners || !this._listeners[event.type]) return;
+
+    this._listeners[event.type].forEach(function(listener) {
+      listener(event);
+    }, this);
+  }
+};
+
+module.exports = EventTarget;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/client.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/client.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/client.js	(revision 533)
@@ -0,0 +1,86 @@
+var net = require('net'),
+    tls = require('tls');
+
+var HybiParser = require('./hybi_parser'),
+    API        = require('./api'),
+    Event      = require('./api/event');
+
+var Client = function(url, protocols, options) {
+  this.url  = url;
+  this._uri = require('url').parse(url);
+
+  this.protocol = '';
+  this.readyState = API.CONNECTING;
+  this.bufferedAmount = 0;
+
+  var secure     = (this._uri.protocol === 'wss:'),
+      self       = this,
+      onConnect  = function() { self._onConnect() },
+      tlsOptions = {};
+
+  if (options && options.verify === false) tlsOptions.rejectUnauthorized = false;
+
+  var connection = secure
+                 ? tls.connect(this._uri.port || 443, this._uri.hostname, tlsOptions, onConnect)
+                 : net.createConnection(this._uri.port || 80, this._uri.hostname);
+
+  this._parser = new HybiParser(this, {masking: true, protocols: protocols});
+  this._stream = connection;
+
+  this._stream.setTimeout(0);
+  this._stream.setNoDelay(true);
+
+  if (!secure) connection.addListener('connect', onConnect);
+
+  connection.addListener('data', function(data) {
+    self._onData(data);
+  });
+  ['close', 'end', 'error'].forEach(function(event) {
+    connection.addListener(event, function() { self.close(1006, '', false) });
+  });
+};
+
+Client.prototype._onConnect = function() {
+  this._handshake = this._parser.createHandshake(this._uri, this._stream);
+  this._message = [];
+  try {
+    this._stream.write(this._handshake.requestData(), 'binary');
+  } catch (e) {}
+};
+
+Client.prototype._onData = function(data) {
+  switch (this.readyState) {
+    case API.CONNECTING:
+      var bytes = this._handshake.parse(data);
+      for (var i = 0, n = bytes.length; i < n; i++)
+        this._message.push(bytes[i]);
+
+      if (!this._handshake.isComplete()) return;
+
+      if (this._handshake.isValid()) {
+        this.protocol = this._handshake.protocol || '';
+        this.readyState = API.OPEN;
+        var event = new Event('open');
+        event.initEvent('open', false, false);
+        this.dispatchEvent(event);
+
+        this._parser.parse(this._message);
+
+      } else {
+        this.readyState = API.CLOSED;
+        var event = new Event('close', {code: 1006, reason: ''});
+        event.initEvent('close', false, false);
+        this.dispatchEvent(event);
+      }
+      break;
+
+    case API.OPEN:
+    case API.CLOSING:
+      this._parser.parse(data);
+  }
+};
+
+for (var key in API) Client.prototype[key] = API[key];
+
+module.exports = Client;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js	(revision 533)
@@ -0,0 +1,98 @@
+var Draft75Parser = function(webSocket) {
+  this._socket = webSocket;
+  this._stage  = 0;
+};
+
+var instance = {
+  getVersion: function() {
+    return 'hixie-75';
+  },
+
+  handshakeResponse: function() {
+    return new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
+                      'Upgrade: WebSocket\r\n' +
+                      'Connection: Upgrade\r\n' +
+                      'WebSocket-Origin: ' + this._socket.request.headers.origin + '\r\n' +
+                      'WebSocket-Location: ' + this._socket.url + '\r\n\r\n',
+                      'utf8');
+  },
+
+  isOpen: function() {
+    return true;
+  },
+
+  parse: function(buffer) {
+    var data, message, value;
+    for (var i = 0, n = buffer.length; i < n; i++) {
+      data = buffer[i];
+
+      switch (this._stage) {
+        case 0:
+          this._parseLeadingByte(data);
+          break;
+
+        case 1:
+          value = (data & 0x7F);
+          this._length = value + 128 * this._length;
+
+          if (this._closing && this._length === 0) {
+            this._socket.close(null, null, false);
+          }
+          else if ((0x80 & data) !== 0x80) {
+            if (this._length === 0) {
+              this._socket.receive('');
+              this._stage = 0;
+            }
+            else {
+              this._buffer = [];
+              this._stage = 2;
+            }
+          }
+          break;
+
+        case 2:
+          if (data === 0xFF) {
+            message = new Buffer(this._buffer);
+            this._socket.receive(message.toString('utf8', 0, this._buffer.length));
+            this._stage = 0;
+          }
+          else {
+            this._buffer.push(data);
+            if (this._length && this._buffer.length === this._length)
+              this._stage = 0;
+          }
+          break;
+      }
+    }
+  },
+
+  _parseLeadingByte: function(data) {
+    if ((0x80 & data) === 0x80) {
+      this._length = 0;
+      this._stage = 1;
+    } else {
+      delete this._length;
+      this._buffer = [];
+      this._stage = 2;
+    }
+  },
+
+  frame: function(data) {
+    if (Buffer.isBuffer(data)) return data;
+
+    var buffer = new Buffer(data, 'utf8'),
+        frame  = new Buffer(buffer.length + 2);
+
+    frame[0] = 0x00;
+    frame[buffer.length + 1] = 0xFF;
+    buffer.copy(frame, 1);
+
+    return frame;
+  }
+};
+
+for (var key in instance)
+  Draft75Parser.prototype[key] = instance[key];
+
+module.exports = Draft75Parser;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js	(revision 533)
@@ -0,0 +1,99 @@
+var crypto        = require('crypto'),
+    Draft75Parser = require('./draft75_parser'),
+    Draft76Parser = function() { Draft75Parser.apply(this, arguments) };
+
+var bridge = function() {};
+bridge.prototype = Draft75Parser.prototype;
+Draft76Parser.prototype = new bridge();
+
+var numberFromKey = function(key) {
+  return parseInt(key.match(/[0-9]/g).join(''), 10);
+};
+
+var spacesInKey = function(key) {
+  return key.match(/ /g).length;
+};
+
+var bigEndian = function(number) {
+  var string = '';
+  [24,16,8,0].forEach(function(offset) {
+    string += String.fromCharCode(number >> offset & 0xFF);
+  });
+  return string;
+};
+
+Draft76Parser.prototype.getVersion = function() {
+  return 'hixie-76';
+};
+
+Draft76Parser.prototype.handshakeResponse = function(head) {
+  var request = this._socket.request, tmp;
+
+  var response = new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
+                            'Upgrade: WebSocket\r\n' +
+                            'Connection: Upgrade\r\n' +
+                            'Sec-WebSocket-Origin: ' + request.headers.origin + '\r\n' +
+                            'Sec-WebSocket-Location: ' + this._socket.url + '\r\n\r\n',
+                            'binary');
+
+  var signature = this.handshakeSignature(head);
+  if (signature) {
+    tmp = new Buffer(response.length + signature.length);
+    response.copy(tmp, 0);
+    signature.copy(tmp, response.length);
+    response = tmp;
+  }
+
+  return response;
+};
+
+Draft76Parser.prototype.isOpen = function() {
+  return !!this._handshakeComplete;
+};
+
+Draft76Parser.prototype.handshakeSignature = function(head) {
+  if (head.length === 0) return null;
+
+  var request = this._socket.request,
+
+      key1    = request.headers['sec-websocket-key1'],
+      value1  = numberFromKey(key1) / spacesInKey(key1),
+
+      key2    = request.headers['sec-websocket-key2'],
+      value2  = numberFromKey(key2) / spacesInKey(key2),
+
+      MD5     = crypto.createHash('md5');
+
+  MD5.update(bigEndian(value1));
+  MD5.update(bigEndian(value2));
+  MD5.update(head.toString('binary'));
+
+  this._handshakeComplete = true;
+  return new Buffer(MD5.digest('binary'), 'binary');
+};
+
+Draft76Parser.prototype.parse = function(data) {
+  if (this._handshakeComplete)
+    return Draft75Parser.prototype.parse.call(this, data);
+
+  return this.handshakeSignature(data);
+};
+
+Draft76Parser.prototype._parseLeadingByte = function(data) {
+  if (data !== 0xFF)
+    return Draft75Parser.prototype._parseLeadingByte.call(this, data);
+
+  this._closing = true;
+  this._length = 0;
+  this._stage = 1;
+};
+
+Draft76Parser.prototype.close = function(code, reason, callback, context) {
+  if (this._closed) return;
+  if (this._closing) this._socket.send(new Buffer([0xFF, 0x00]));
+  this._closed = true;
+  if (callback) callback.call(context);
+};
+
+module.exports = Draft76Parser;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js	(revision 533)
@@ -0,0 +1,355 @@
+var crypto    = require('crypto'),
+    Handshake = require('./hybi_parser/handshake'),
+    Reader    = require('./hybi_parser/stream_reader');
+
+var HybiParser = function(webSocket, options) {
+  this._reset();
+  this._socket    = webSocket;
+  this._reader    = new Reader();
+  this._stage     = 0;
+  this._masking   = options && options.masking;
+  this._protocols = options && options.protocols;
+
+  this._pingCallbacks = {};
+
+  if (typeof this._protocols === 'string')
+    this._protocols = this._protocols.split(/\s*,\s*/);
+};
+
+HybiParser.mask = function(payload, mask, offset) {
+  if (mask.length === 0) return payload;
+  offset = offset || 0;
+
+  for (var i = 0, n = payload.length - offset; i < n; i++) {
+    payload[offset + i] = payload[offset + i] ^ mask[i % 4];
+  }
+  return payload;
+};
+
+var instance = {
+  BYTE:   255,
+  FIN:    128,
+  MASK:   128,
+  RSV1:   64,
+  RSV2:   32,
+  RSV3:   16,
+  OPCODE: 15,
+  LENGTH: 127,
+
+  OPCODES: {
+    continuation: 0,
+    text:         1,
+    binary:       2,
+    close:        8,
+    ping:         9,
+    pong:         10
+  },
+
+  ERRORS: {
+    normal_closure:       1000,
+    going_away:           1001,
+    protocol_error:       1002,
+    unacceptable:         1003,
+    encoding_error:       1007,
+    policy_violation:     1008,
+    too_large:            1009,
+    extension_error:      1010,
+    unexpected_condition: 1011
+  },
+
+  FRAGMENTED_OPCODES: [0,1,2],
+  OPENING_OPCODES:    [1,2],
+
+  ERROR_CODES: [1000,1001,1002,1003,1007,1008,1009,1010,1011],
+
+  UTF8_MATCH: /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/,
+
+  getVersion: function() {
+    var version = this._socket.request.headers['sec-websocket-version'];
+    return 'hybi-' + version;
+  },
+
+  handshakeResponse: function() {
+    var secKey = this._socket.request.headers['sec-websocket-key'];
+    if (!secKey) return null;
+
+    var SHA1 = crypto.createHash('sha1');
+    SHA1.update(secKey + Handshake.GUID);
+
+    var accept    = SHA1.digest('base64'),
+        protos    = this._socket.request.headers['sec-websocket-protocol'],
+        supported = this._protocols,
+        proto,
+
+        headers = [
+          'HTTP/1.1 101 Switching Protocols',
+          'Upgrade: websocket',
+          'Connection: Upgrade',
+          'Sec-WebSocket-Accept: ' + accept
+        ];
+
+    if (protos !== undefined && supported !== undefined) {
+      if (typeof protos === 'string') protos = protos.split(/\s*,\s*/);
+      proto = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0];
+      if (proto) {
+        this.protocol = proto;
+        headers.push('Sec-WebSocket-Protocol: ' + proto);
+      }
+    }
+
+    return new Buffer(headers.concat('','').join('\r\n'), 'utf8');
+  },
+
+  isOpen: function() {
+    return true;
+  },
+
+  createHandshake: function(uri) {
+    return new Handshake(uri, this._protocols);
+  },
+
+  parse: function(data) {
+    this._reader.put(data);
+    var buffer = true;
+    while (buffer) {
+      switch (this._stage) {
+        case 0:
+          buffer = this._reader.read(1);
+          if (buffer) this._parseOpcode(buffer[0]);
+          break;
+
+        case 1:
+          buffer = this._reader.read(1);
+          if (buffer) this._parseLength(buffer[0]);
+          break;
+
+        case 2:
+          buffer = this._reader.read(this._lengthSize);
+          if (buffer) this._parseExtendedLength(buffer);
+          break;
+
+        case 3:
+          buffer = this._reader.read(4);
+          if (buffer) {
+            this._mask  = buffer;
+            this._stage = 4;
+          }
+          break;
+
+        case 4:
+          buffer = this._reader.read(this._length);
+          if (buffer) {
+            this._payload = buffer;
+            this._emitFrame();
+            this._stage = 0;
+          }
+          break;
+      }
+    }
+  },
+
+  _parseOpcode: function(data) {
+    var rsvs = [this.RSV1, this.RSV2, this.RSV3].filter(function(rsv) {
+      return (data & rsv) === rsv;
+    }, this);
+
+    if (rsvs.length > 0) return this._socket.close(this.ERRORS.protocol_error, null, false);
+
+    this._final   = (data & this.FIN) === this.FIN;
+    this._opcode  = (data & this.OPCODE);
+    this._mask    = [];
+    this._payload = [];
+
+    var valid = false;
+
+    for (var key in this.OPCODES) {
+      if (this.OPCODES[key] === this._opcode)
+        valid = true;
+    }
+    if (!valid) return this._socket.close(this.ERRORS.protocol_error, null, false);
+
+    if (this.FRAGMENTED_OPCODES.indexOf(this._opcode) < 0 && !this._final)
+      return this._socket.close(this.ERRORS.protocol_error, null, false);
+
+    if (this._mode && this.OPENING_OPCODES.indexOf(this._opcode) >= 0)
+      return this._socket.close(this.ERRORS.protocol_error, null, false);
+
+    this._stage = 1;
+  },
+
+  _parseLength: function(data) {
+    this._masked = (data & this.MASK) === this.MASK;
+    this._length = (data & this.LENGTH);
+
+    if (this._length >= 0 && this._length <= 125) {
+      this._stage = this._masked ? 3 : 4;
+    } else {
+      this._lengthBuffer = [];
+      this._lengthSize   = (this._length === 126 ? 2 : 8);
+      this._stage        = 2;
+    }
+  },
+
+  _parseExtendedLength: function(buffer) {
+    this._length = this._getInteger(buffer);
+    this._stage  = this._masked ? 3 : 4;
+  },
+
+  frame: function(data, type, code) {
+    if (this._closed) return null;
+
+    var isText = (typeof data === 'string'),
+        opcode = this.OPCODES[type || (isText ? 'text' : 'binary')],
+        buffer = isText ? new Buffer(data, 'utf8') : data,
+        insert = code ? 2 : 0,
+        length = buffer.length + insert,
+        header = (length <= 125) ? 2 : (length <= 65535 ? 4 : 10),
+        offset = header + (this._masking ? 4 : 0),
+        masked = this._masking ? this.MASK : 0,
+        frame  = new Buffer(length + offset),
+        BYTE   = this.BYTE,
+        mask, i;
+
+    frame[0] = this.FIN | opcode;
+
+    if (length <= 125) {
+      frame[1] = masked | length;
+    } else if (length <= 65535) {
+      frame[1] = masked | 126;
+      frame[2] = Math.floor(length / 256);
+      frame[3] = length & BYTE;
+    } else {
+      frame[1] = masked | 127;
+      frame[2] = Math.floor(length / Math.pow(2,56)) & BYTE;
+      frame[3] = Math.floor(length / Math.pow(2,48)) & BYTE;
+      frame[4] = Math.floor(length / Math.pow(2,40)) & BYTE;
+      frame[5] = Math.floor(length / Math.pow(2,32)) & BYTE;
+      frame[6] = Math.floor(length / Math.pow(2,24)) & BYTE;
+      frame[7] = Math.floor(length / Math.pow(2,16)) & BYTE;
+      frame[8] = Math.floor(length / Math.pow(2,8))  & BYTE;
+      frame[9] = length & BYTE;
+    }
+
+    if (code) {
+      frame[offset]   = Math.floor(code / 256) & BYTE;
+      frame[offset+1] = code & BYTE;
+    }
+    buffer.copy(frame, offset + insert);
+
+    if (this._masking) {
+      mask = [Math.floor(Math.random() * 256), Math.floor(Math.random() * 256),
+              Math.floor(Math.random() * 256), Math.floor(Math.random() * 256)];
+      new Buffer(mask).copy(frame, header);
+      HybiParser.mask(frame, mask, offset);
+    }
+
+    return frame;
+  },
+
+  ping: function(message, callback, context) {
+    message = message || '';
+    if (callback) this._pingCallbacks[message] = [callback, context];
+    return this._socket.send(message, 'ping');
+  },
+
+  close: function(code, reason, callback, context) {
+    if (this._closed) return;
+    if (callback) this._closingCallback = [callback, context];
+    this._socket.send(reason || '', 'close', code || this.ERRORS.normal_closure);
+    this._closed = true;
+  },
+
+  buffer: function(fragment) {
+    for (var i = 0, n = fragment.length; i < n; i++)
+      this._buffer.push(fragment[i]);
+  },
+
+  _emitFrame: function() {
+    var payload = HybiParser.mask(this._payload, this._mask),
+        opcode  = this._opcode;
+
+    if (opcode === this.OPCODES.continuation) {
+      if (!this._mode) return this._socket.close(this.ERRORS.protocol_error, null, false);
+      this.buffer(payload);
+      if (this._final) {
+        var message = new Buffer(this._buffer);
+        if (this._mode === 'text') message = this._encode(message);
+        this._reset();
+        if (message !== null) this._socket.receive(message);
+        else this._socket.close(this.ERRORS.encoding_error, null, false);
+      }
+    }
+    else if (opcode === this.OPCODES.text) {
+      if (this._final) {
+        var message = this._encode(payload);
+        if (message !== null) this._socket.receive(message);
+        else this._socket.close(this.ERRORS.encoding_error, null, false);
+      } else {
+        this._mode = 'text';
+        this.buffer(payload);
+      }
+    }
+    else if (opcode === this.OPCODES.binary) {
+      if (this._final) {
+        this._socket.receive(payload);
+      } else {
+        this._mode = 'binary';
+        this.buffer(payload);
+      }
+    }
+    else if (opcode === this.OPCODES.close) {
+      var code   = (payload.length >= 2) ? 256 * payload[0] + payload[1] : null,
+          reason = (payload.length > 2) ? this._encode(payload.slice(2)) : null;
+
+      if (!(payload.length === 0) &&
+          !(code !== null && code >= 3000 && code < 5000) &&
+          this.ERROR_CODES.indexOf(code) < 0)
+        code = this.ERRORS.protocol_error;
+
+      if (payload.length > 125 || (payload.length > 2 && !reason))
+        code = this.ERRORS.protocol_error;
+
+      this._socket.close(code, (payload.length > 2) ? reason : null, false);
+      if (this._closingCallback)
+        this._closingCallback[0].call(this._closingCallback[1]);
+    }
+    else if (opcode === this.OPCODES.ping) {
+      if (payload.length > 125) return this._socket.close(this.ERRORS.protocol_error, null, false);
+      this._socket.send(payload, 'pong');
+    }
+    else if (opcode === this.OPCODES.pong) {
+      var callbacks = this._pingCallbacks,
+          message   = this._encode(payload),
+          callback  = callbacks[message];
+
+      delete callbacks[message];
+      if (callback) callback[0].call(callback[1]);
+    }
+  },
+
+  _reset: function() {
+    this._mode   = null;
+    this._buffer = [];
+  },
+
+  _encode: function(buffer) {
+    try {
+      var string = buffer.toString('binary', 0, buffer.length);
+      if (!this.UTF8_MATCH.test(string)) return null;
+    } catch (e) {}
+    return buffer.toString('utf8', 0, buffer.length);
+  },
+
+  _getInteger: function(bytes) {
+    var number = 0;
+    for (var i = 0, n = bytes.length; i < n; i++)
+      number += bytes[i] << (8 * (n - 1 - i));
+    return number;
+  }
+};
+
+for (var key in instance)
+  HybiParser.prototype[key] = instance[key];
+
+module.exports = HybiParser;
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js	(revision 533)
@@ -0,0 +1,91 @@
+var crypto = require('crypto');
+
+var Handshake = function(uri, protocols) {
+  this._uri = uri;
+  this._protocols = protocols;
+
+  var buffer = new Buffer(16), i = 16;
+  while (i--) buffer[i] = Math.floor(Math.random() * 256);
+  this._key = buffer.toString('base64');
+
+  var SHA1 = crypto.createHash('sha1');
+  SHA1.update(this._key + Handshake.GUID);
+  this._accept = SHA1.digest('base64');
+
+  var HTTPParser = process.binding('http_parser').HTTPParser,
+      parser     = new HTTPParser(HTTPParser.RESPONSE || 'response'),
+      current    = null,
+      self       = this;
+
+  this._nodeVersion = HTTPParser.RESPONSE ? 6 : 4;
+  this._complete    = false;
+  this._headers     = {};
+  this._parser      = parser;
+
+  parser.onHeaderField = function(b, start, length) {
+    current = b.toString('utf8', start, start + length);
+  };
+  parser.onHeaderValue = function(b, start, length) {
+    self._headers[current] = b.toString('utf8', start, start + length);
+  };
+  parser.onHeadersComplete = function(info) {
+    self._status = info.statusCode;
+    var headers = info.headers;
+    if (!headers) return;
+    for (var i = 0, n = headers.length; i < n; i += 2)
+      self._headers[headers[i]] = headers[i+1];
+  };
+  parser.onMessageComplete = function() {
+    self._complete = true;
+  };
+};
+
+Handshake.GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
+
+Handshake.prototype.requestData = function() {
+  var u = this._uri;
+
+  var headers = [
+    'GET ' + (u.pathname || '/') + (u.search || '') + ' HTTP/1.1',
+    'Host: ' + u.hostname + (u.port ? ':' + u.port : ''),
+    'Upgrade: websocket',
+    'Connection: Upgrade',
+    'Sec-WebSocket-Key: ' + this._key,
+    'Sec-WebSocket-Version: 13'
+  ];
+
+  if (this._protocols)
+    headers.push('Sec-WebSocket-Protocol: ' + this._protocols.join(', '));
+
+  return new Buffer(headers.concat('','').join('\r\n'), 'utf8');
+};
+
+Handshake.prototype.parse = function(data) {
+  var consumed = this._parser.execute(data, 0, data.length),
+      offset   = (this._nodeVersion < 6) ? 1 : 0;
+
+  return (consumed === data.length) ? [] : data.slice(consumed + offset);
+};
+
+Handshake.prototype.isComplete = function() {
+  return this._complete;
+};
+
+Handshake.prototype.isValid = function() {
+  if (this._status !== 101) return false;
+
+  var upgrade    = this._headers.Upgrade,
+      connection = this._headers.Connection,
+      protocol   = this._headers['Sec-WebSocket-Protocol'];
+
+  this.protocol = this._protocols && this._protocols.indexOf(protocol) >= 0
+                ? protocol
+                : null;
+
+  return upgrade && /^websocket$/i.test(upgrade) &&
+         connection && connection.split(/\s*,\s*/).indexOf('Upgrade') >= 0 &&
+         ((!this._protocols && !protocol) || this.protocol) &&
+         this._headers['Sec-WebSocket-Accept'] === this._accept;
+};
+
+module.exports = Handshake;
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js	(revision 533)
@@ -0,0 +1,43 @@
+var StreamReader = function() {
+  this._queue  = [];
+  this._cursor = 0;
+};
+
+StreamReader.prototype.read = function(bytes) {
+  return this._readBuffer(bytes);
+};
+
+StreamReader.prototype.put = function(buffer) {
+  if (!buffer || buffer.length === 0) return;
+  if (!buffer.copy) buffer = new Buffer(buffer);
+  this._queue.push(buffer);
+};
+
+StreamReader.prototype._readBuffer = function(length) {
+  var buffer = new Buffer(length),
+      queue  = this._queue,
+      remain = length,
+      n      = queue.length,
+      i      = 0,
+      chunk, offset, size;
+
+  if (remain === 0) return buffer;
+
+  while (remain > 0 && i < n) {
+    chunk = queue[i];
+    offset = (i === 0) ? this._cursor : 0;
+    size = Math.min(remain, chunk.length - offset);
+    chunk.copy(buffer, length - remain, offset, offset + size);
+    remain -= size;
+    i += 1;
+  }
+
+  if (remain > 0) return null;
+
+  queue.splice(0, i-1);
+  this._cursor = (i === 1 ? this._cursor : 0) + size;
+
+  return buffer;
+};
+
+module.exports = StreamReader;
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/package.json	(revision 533)
@@ -0,0 +1,53 @@
+{
+  "name": "faye-websocket",
+  "description": "Standards-compliant WebSocket server and client",
+  "homepage": "http://github.com/faye/faye-websocket-node",
+  "author": {
+    "name": "James Coglan",
+    "email": "jcoglan@gmail.com",
+    "url": "http://jcoglan.com/"
+  },
+  "keywords": [
+    "websocket",
+    "eventsource"
+  ],
+  "version": "0.4.4",
+  "engines": {
+    "node": ">=0.4.0"
+  },
+  "main": "./lib/faye/websocket",
+  "devDependencies": {
+    "jsclass": "",
+    "pace": ""
+  },
+  "scripts": {
+    "test": "node spec/runner.js"
+  },
+  "bugs": {
+    "url": "http://github.com/faye/faye-websocket-node/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://www.opensource.org/licenses/mit-license.php"
+    }
+  ],
+  "repositories": [
+    {
+      "type": "git",
+      "url": "git://github.com/faye/faye-websocket-node.git"
+    }
+  ],
+  "readme": "# faye-websocket\n\n* Travis CI build: [<img src=\"https://secure.travis-ci.org/faye/faye-websocket-node.png\" />](http://travis-ci.org/faye/faye-websocket-node)\n* Autobahn tests: [server](http://faye.jcoglan.com/autobahn/servers/), [client](http://faye.jcoglan.com/autobahn/clients/)\n\nThis is a robust, general-purpose WebSocket implementation extracted from the\n[Faye](http://faye.jcoglan.com) project. It provides classes for easily building\nWebSocket servers and clients in Node. It does not provide a server itself, but\nrather makes it easy to handle WebSocket connections within an existing\n[Node](http://nodejs.org/) application. It does not provide any abstraction\nother than the standard [WebSocket API](http://dev.w3.org/html5/websockets/).\n\nIt also provides an abstraction for handling [EventSource](http://dev.w3.org/html5/eventsource/)\nconnections, which are one-way connections that allow the server to push data to\nthe client. They are based on streaming HTTP responses and can be easier to\naccess via proxies than WebSockets.\n\nThe server-side socket can process [draft-75](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75),\n[draft-76](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76),\n[hybi-07](http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07)\nand later versions of the protocol. It selects protocol versions automatically,\nsupports both `text` and `binary` messages, and transparently handles `ping`,\n`pong`, `close` and fragmented messages.\n\n\n## Handling WebSocket connections in Node\n\nYou can handle WebSockets on the server side by listening for HTTP Upgrade\nrequests, and creating a new socket for the request. This socket object exposes\nthe usual WebSocket methods for receiving and sending messages. For example this\nis how you'd implement an echo server:\n\n```js\nvar WebSocket = require('faye-websocket'),\n    http      = require('http');\n\nvar server = http.createServer();\n\nserver.addListener('upgrade', function(request, socket, head) {\n  var ws = new WebSocket(request, socket, head);\n  \n  ws.onmessage = function(event) {\n    ws.send(event.data);\n  };\n  \n  ws.onclose = function(event) {\n    console.log('close', event.code, event.reason);\n    ws = null;\n  };\n});\n\nserver.listen(8000);\n```\n\nNote that under certain circumstances (notably a draft-76 client connecting\nthrough an HTTP proxy), the WebSocket handshake will not be complete after you\ncall `new WebSocket()` because the server will not have received the entire\nhandshake from the client yet. In this case, calls to `ws.send()` will buffer\nthe message in memory until the handshake is complete, at which point any\nbuffered messages will be sent to the client.\n\nIf you need to detect when the WebSocket handshake is complete, you can use the\n`onopen` event.\n\nIf the connection's protocol version supports it, you can call `ws.ping()` to\nsend a ping message and wait for the client's response. This method takes a\nmessage string, and an optional callback that fires when a matching pong message\nis received. It returns `true` iff a ping message was sent. If the client does\nnot support ping/pong, this method sends no data and returns `false`.\n\n```js\nws.ping('Mic check, one, two', function() {\n  // fires when pong is received\n});\n```\n\n\n## Using the WebSocket client\n\nThe client supports both the plain-text `ws` protocol and the encrypted `wss`\nprotocol, and has exactly the same interface as a socket you would use in a web\nbrowser. On the wire it identifies itself as hybi-13.\n\n```js\nvar WebSocket = require('faye-websocket'),\n    ws        = new WebSocket.Client('ws://www.example.com/');\n\nws.onopen = function(event) {\n  console.log('open');\n  ws.send('Hello, world!');\n};\n\nws.onmessage = function(event) {\n  console.log('message', event.data);\n};\n\nws.onclose = function(event) {\n  console.log('close', event.code, event.reason);\n  ws = null;\n};\n```\n\n\n## Subprotocol negotiation\n\nThe WebSocket protocol allows peers to select and identify the application\nprotocol to use over the connection. On the client side, you can set which\nprotocols the client accepts by passing a list of protocol names when you\nconstruct the socket:\n\n```js\nvar ws = new WebSocket.Client('ws://www.example.com/', ['irc', 'amqp']);\n```\n\nOn the server side, you can likewise pass in the list of protocols the server\nsupports after the other constructor arguments:\n\n```js\nvar ws = new WebSocket(request, socket, head, ['irc', 'amqp']);\n```\n\nIf the client and server agree on a protocol, both the client- and server-side\nsocket objects expose the selected protocol through the `ws.protocol` property.\nIf they cannot agree on a protocol to use, the client closes the connection.\n\n\n## WebSocket API\n\nThe WebSocket API consists of several event handlers and a method for sending\nmessages.\n\n* <b><tt>onopen</tt></b> fires when the socket connection is established. Event\n  has no attributes.\n* <b><tt>onerror</tt></b> fires when the connection attempt fails. Event has no\n  attributes.\n* <b><tt>onmessage</tt></b> fires when the socket receives a message. Event has\n  one attribute, <b><tt>data</tt></b>, which is either a `String` (for text\n  frames) or a `Buffer` (for binary frames).\n* <b><tt>onclose</tt></b> fires when either the client or the server closes the\n  connection. Event has two optional attributes, <b><tt>code</tt></b> and\n  <b><tt>reason</tt></b>, that expose the status code and message sent by the\n  peer that closed the connection.\n* <b><tt>send(message)</tt></b> accepts either a `String` or a `Buffer` and\n  sends a text or binary message over the connection to the other peer.\n* <b><tt>close(code, reason)</tt></b> closes the connection, sending the given\n  status code and reason text, both of which are optional.\n* <b><tt>protocol</tt></b> is a string (which may be empty) identifying the\n  subprotocol the socket is using.\n\n\n## Handling EventSource connections in Node\n\nEventSource connections provide a very similar interface, although because they\nonly allow the server to send data to the client, there is no `onmessage` API.\nEventSource allows the server to push text messages to the client, where each\nmessage has an optional event-type and ID.\n\n```js\nvar WebSocket   = require('faye-websocket'),\n    EventSource = WebSocket.EventSource,\n    http        = require('http');\n\nvar server = http.createServer();\n\nserver.addListener('request', function(request, response) {\n  if (EventSource.isEventSource(request)) {\n    var es = new EventSource(request, response);\n    console.log('open', es.url, es.lastEventId);\n    \n    // Periodically send messages\n    var loop = setInterval(function() { es.send('Hello') }, 1000);\n    \n    es.onclose = function() {\n      clearInterval(loop);\n      es = null;\n    };\n  \n  } else {\n    // Normal HTTP request\n    response.writeHead(200, {'Content-Type': 'text/plain'});\n    response.write('Hello');\n    response.end();\n  }\n});\n\nserver.listen(8000);\n```\n\nThe `send` method takes two optional parameters, `event` and `id`. The default\nevent-type is `'message'` with no ID. For example, to send a `notification`\nevent with ID `99`:\n\n```js\nes.send('Breaking News!', {event: 'notification', id: '99'});\n```\n\nThe `EventSource` object exposes the following properties:\n\n* <b><tt>url</tt></b> is a string containing the URL the client used to create\n  the EventSource.\n* <b><tt>lastEventId</tt></b> is a string containing the last event ID\n  received by the client. You can use this when the client reconnects after a\n  dropped connection to determine which messages need resending.\n\nWhen you initialize an EventSource with ` new EventSource()`, you can pass\nconfiguration options after the `response` parameter. Available options are:\n\n* <b><tt>retry</tt></b> is a number that tells the client how long (in seconds)\n  it should wait after a dropped connection before attempting to reconnect.\n* <b><tt>ping</tt></b> is a number that tells the server how often (in seconds)\n  to send 'ping' packets to the client to keep the connection open, to defeat\n  timeouts set by proxies. The client will ignore these messages.\n\nFor example, this creates a connection that pings every 15 seconds and is\nretryable every 10 seconds if the connection is broken:\n\n```js\nvar es = new EventSource(request, response, {ping: 15, retry: 10});\n```\n\nYou can send a ping message at any time by calling `es.ping()`. Unlike WebSocket,\nthe client does not send a response to this; it is merely to send some data over\nthe wire to keep the connection alive.\n\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2013 James Coglan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the 'Software'), to deal in\nthe Software without restriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the\nSoftware, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n",
+  "readmeFilename": "README.markdown",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/faye/faye-websocket-node.git"
+  },
+  "_id": "faye-websocket@0.4.4",
+  "dist": {
+    "shasum": "aa073887f0a1de75687820d1a7fe595b0766ffbd"
+  },
+  "_from": "faye-websocket@~0.4.3",
+  "_resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/client_spec.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/client_spec.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/client_spec.js	(revision 533)
@@ -0,0 +1,175 @@
+var Client = require('../../../lib/faye/websocket/client')
+
+JS.ENV.WebSocketSteps = JS.Test.asyncSteps({
+  server: function(port, secure, callback) {
+    this._adapter = new EchoServer()
+    this._adapter.listen(port, secure)
+    this._port = port
+    setTimeout(callback, 100)
+  },
+
+  stop: function(callback) {
+    this._adapter.stop()
+    setTimeout(callback, 100)
+  },
+
+  open_socket: function(url, protocols, callback) {
+    var done = false,
+        self = this,
+
+        resume = function(open) {
+                   if (done) return
+                   done = true
+                   self._open = open
+                   callback()
+                 }
+
+    this._ws = new Client(url, protocols, {verify: false})
+
+    this._ws.onopen  = function() { resume(true)  }
+    this._ws.onclose = function() { resume(false) }
+  },
+
+  close_socket: function(callback) {
+    var self = this
+    this._ws.onclose = function() {
+      self._open = false
+      callback()
+    }
+    this._ws.close()
+  },
+
+  check_open: function(callback) {
+    this.assert( this._open )
+    callback()
+  },
+
+  check_closed: function(callback) {
+    this.assert( !this._open )
+    callback()
+  },
+
+  check_protocol: function(protocol, callback) {
+    this.assertEqual( protocol, this._ws.protocol )
+    callback()
+  },
+
+  listen_for_message: function(callback) {
+    var self = this
+    this._ws.addEventListener('message', function(message) { self._message = message.data })
+    callback()
+  },
+
+  send_message: function(message, callback) {
+    this._ws.send(message)
+    setTimeout(callback, 100)
+  },
+
+  check_response: function(message, callback) {
+    this.assertEqual( message, this._message )
+    callback()
+  },
+
+  check_no_response: function(callback) {
+    this.assert( !this._message )
+    callback()
+  }
+})
+
+
+JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
+  include(WebSocketSteps)
+
+  before(function() {
+    this.protocols       = ["foo", "echo"]
+    this.plain_text_url  = "ws://localhost:8000/bayeux"
+    this.secure_url      = "wss://localhost:8000/bayeux"
+  })
+
+  sharedBehavior("socket client", function() { with(this) {
+    it("can open a connection", function() { with(this) {
+      open_socket(socket_url, protocols)
+      check_open()
+      check_protocol("echo")
+    }})
+
+    it("cannot open a connection with unacceptable protocols", function() { with(this) {
+      open_socket(socket_url, ["foo"])
+      check_closed()
+    }})
+
+    it("can close the connection", function() { with(this) {
+      open_socket(socket_url, protocols)
+      close_socket()
+      check_closed()
+    }})
+
+    describe("in the OPEN state", function() { with(this) {
+      before(function() { with(this) {
+        open_socket(socket_url, protocols)
+      }})
+
+      it("can send and receive messages", function() { with(this) {
+        listen_for_message()
+        send_message("I expect this to be echoed")
+        check_response("I expect this to be echoed")
+      }})
+
+      it("sends numbers as strings", function() { with(this) {
+        listen_for_message()
+        send_message(13)
+        check_response("13")
+      }})
+
+      it("sends booleans as strings", function() { with(this) {
+        listen_for_message()
+        send_message(false)
+        check_response("false")
+      }})
+
+      it("sends arrays as strings", function() { with(this) {
+        listen_for_message()
+        send_message([13,14,15])
+        check_response("13,14,15")
+      }})
+    }})
+
+    describe("in the CLOSED state", function() { with(this) {
+      before(function() { with(this) {
+        open_socket(socket_url, protocols)
+        close_socket()
+      }})
+
+      it("cannot send and receive messages", function() { with(this) {
+        listen_for_message()
+        send_message("I expect this to be echoed")
+        check_no_response()
+      }})
+    }})
+  }})
+
+  describe("with a plain-text server", function() { with(this) {
+    before(function() {
+      this.socket_url  = this.plain_text_url
+      this.blocked_url = this.secure_url
+    })
+
+    before(function() { this.server(8000, false) })
+    after (function() { this.stop() })
+
+    behavesLike("socket client")
+  }})
+
+  describe("with a secure server", function() { with(this) {
+    before(function() {
+      this.socket_url  = this.secure_url
+      this.blocked_url = this.plain_text_url
+    })
+
+    before(function() { this.server(8000, true) })
+    after (function() { this.stop() })
+
+    behavesLike("socket client")
+  }})
+}})
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js	(revision 533)
@@ -0,0 +1,72 @@
+var Draft75Parser = require('../../../lib/faye/websocket/draft75_parser')
+
+JS.ENV.Draft75ParserSpec = JS.Test.describe("Draft75Parser", function() { with(this) {
+  before(function() { with(this) {
+    this.webSocket = {dispatchEvent: function() {}}
+    this.parser = new Draft75Parser(webSocket)
+  }})
+
+  describe("parse", function() { with(this) {
+    sharedBehavior("draft-75 parser", function() { with(this) {
+      it("parses text frames", function() { with(this) {
+        expect(webSocket, "receive").given("Hello")
+        parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
+      }})
+
+      it("parses multiple frames from the same packet", function() { with(this) {
+        expect(webSocket, "receive").given("Hello").exactly(2)
+        parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
+      }})
+
+      it("parses text frames beginning 0x00-0x7F", function() { with(this) {
+        expect(webSocket, "receive").given("Hello")
+        parser.parse([0x66, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
+      }})
+
+      it("ignores frames with a length header", function() { with(this) {
+        expect(webSocket, "receive").exactly(0)
+        parser.parse([0x80, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f])
+      }})
+
+      it("parses text following an ignored block", function() { with(this) {
+        expect(webSocket, "receive").given("Hello")
+        parser.parse([0x80, 0x02, 0x48, 0x65, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
+      }})
+
+      it("parses multibyte text frames", function() { with(this) {
+        expect(webSocket, "receive").given("Apple = ï£¿")
+        parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff])
+      }})
+
+      it("parses frames received in several packets", function() { with(this) {
+        expect(webSocket, "receive").given("Apple = ï£¿")
+        parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65])
+        parser.parse([0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff])
+      }})
+
+      it("parses fragmented frames", function() { with(this) {
+        expect(webSocket, "receive").given("Hello")
+        parser.parse([0x00, 0x48, 0x65, 0x6c])
+        parser.parse([0x6c, 0x6f, 0xff])
+      }})
+    }})
+
+    behavesLike("draft-75 parser")
+
+    it("does not close the socket if a 76 close frame is received", function() { with(this) {
+      expect(webSocket, "close").exactly(0)
+      expect(webSocket, "receive").given("")
+      parser.parse([0xFF, 0x00])
+    }})
+  }})
+
+  describe("frame", function() { with(this) {
+    it("returns the given string formatted as a WebSocket frame", function() { with(this) {
+      assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") )
+    }})
+
+    it("encodes multibyte characters correctly", function() { with(this) {
+      assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ï£¿") )
+    }})
+  }})
+}})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js	(revision 533)
@@ -0,0 +1,28 @@
+var Draft76Parser = require('../../../lib/faye/websocket/draft76_parser')
+
+JS.ENV.Draft76ParserSpec = JS.Test.describe("Draft76Parser", function() { with(this) {
+  before(function() { with(this) {
+    this.webSocket = {dispatchEvent: function() {}}
+    this.parser = new Draft76Parser(webSocket)
+    parser._handshakeComplete = true
+  }})
+
+  describe("parse", function() { with(this) {
+    behavesLike("draft-75 parser")
+
+    it("closes the socket if a close frame is received", function() { with(this) {
+      expect(webSocket, "close")
+      parser.parse([0xFF, 0x00])
+    }})
+  }})
+
+  describe("frame", function() { with(this) {
+    it("returns the given string formatted as a WebSocket frame", function() { with(this) {
+      assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") )
+    }})
+
+    it("encodes multibyte characters correctly", function() { with(this) {
+      assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ï£¿") )
+    }})
+  }})
+}})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js	(revision 533)
@@ -0,0 +1,148 @@
+var HybiParser = require('../../../lib/faye/websocket/hybi_parser')
+
+JS.ENV.HybiParserSpec = JS.Test.describe("HybiParser", function() { with(this) {
+  before(function() { with(this) {
+    this.webSocket = {dispatchEvent: function() {}}
+    this.parser = new HybiParser(webSocket)
+  }})
+
+  define("parse", function() {
+    var bytes = [];
+    for (var i = 0, n = arguments.length; i < n; i++) bytes = bytes.concat(arguments[i])
+    this.parser.parse(new Buffer(bytes))
+  })
+
+  define("buffer", function(string) {
+    return {
+      equals: function(buffer) {
+        return buffer.toString('utf8', 0, buffer.length) === string
+      }
+    }
+  })
+
+  describe("parse", function() { with(this) {
+    define("mask", function() {
+      return this._mask = this._mask || [1,2,3,4].map(function() { return Math.floor(Math.random() * 255) })
+    })
+
+    define("maskMessage", function(bytes) {
+      var output = []
+      Array.prototype.forEach.call(bytes, function(b, i) {
+        output[i] = bytes[i] ^ this.mask()[i % 4]
+      }, this)
+      return output
+    })
+
+    it("parses unmasked text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Hello")
+      parse([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f])
+    }})
+
+    it("parses multiple frames from the same packet", function() { with(this) {
+      expect(webSocket, "receive").given("Hello").exactly(2)
+      parse([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f])
+    }})
+
+    it("parses empty text frames", function() { with(this) {
+      expect(webSocket, "receive").given("")
+      parse([0x81, 0x00])
+    }})
+
+    it("parses fragmented text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Hello")
+      parse([0x01, 0x03, 0x48, 0x65, 0x6c])
+      parse([0x80, 0x02, 0x6c, 0x6f])
+    }})
+
+    it("parses masked text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Hello")
+      parse([0x81, 0x85], mask(), maskMessage([0x48, 0x65, 0x6c, 0x6c, 0x6f]))
+    }})
+
+    it("parses masked empty text frames", function() { with(this) {
+      expect(webSocket, "receive").given("")
+      parse([0x81, 0x80], mask(), maskMessage([]))
+    }})
+
+    it("parses masked fragmented text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Hello")
+      parse([0x01, 0x81], mask(), maskMessage([0x48]))
+      parse([0x80, 0x84], mask(), maskMessage([0x65, 0x6c, 0x6c, 0x6f]))
+    }})
+
+    it("closes the socket if the frame has an unrecognized opcode", function() { with(this) {
+      expect(webSocket, "close").given(1002, null, false)
+      parse([0x83, 0x00])
+    }})
+
+    it("closes the socket if a close frame is received", function() { with(this) {
+      expect(webSocket, "close").given(1000, "Hello", false)
+      parse([0x88, 0x07, 0x03, 0xe8, 0x48, 0x65, 0x6c, 0x6c, 0x6f])
+    }})
+
+    it("parses unmasked multibyte text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Apple = ï£¿")
+      parse([0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf])
+    }})
+
+    it("parses frames received in several packets", function() { with(this) {
+      expect(webSocket, "receive").given("Apple = ï£¿")
+      parse([0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c])
+      parse([0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf])
+    }})
+
+    it("parses fragmented multibyte text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Apple = ï£¿")
+      parse([0x01, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3])
+      parse([0x80, 0x01, 0xbf])
+    }})
+
+    it("parses masked multibyte text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Apple = ï£¿")
+      parse([0x81, 0x8b], mask(), maskMessage([0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]))
+    }})
+
+    it("parses masked fragmented multibyte text frames", function() { with(this) {
+      expect(webSocket, "receive").given("Apple = ï£¿")
+      parse([0x01, 0x8a], mask(), maskMessage([0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3]))
+      parse([0x80, 0x81], mask(), maskMessage([0xbf]))
+    }})
+
+    it("parses unmasked medium-length text frames", function() { with(this) {
+      expect(webSocket, "receive").given("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello")
+      parse([129, 126, 0, 200, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111])
+    }})
+
+    it("parses masked medium-length text frames", function() { with(this) {
+      expect(webSocket, "receive").given("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello")
+      parse([129, 254, 0, 200], mask(), maskMessage([72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111]))
+    }})
+
+    it("replies to pings with a pong", function() { with(this) {
+      expect(webSocket, "send").given(buffer("OHAI"), "pong")
+      parse([0x89, 0x04, 0x4f, 0x48, 0x41, 0x49])
+    }})
+  }})
+
+  describe("frame", function() { with(this) {
+    it("returns the given string formatted as a WebSocket frame", function() { with(this) {
+      assertBufferEqual( [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f], parser.frame("Hello") )
+    }})
+
+    it("encodes multibyte characters correctly", function() { with(this) {
+      assertBufferEqual( [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf], parser.frame("Apple = ï£¿") )
+    }})
+
+    it("encodes medium-length strings using extra length bytes", function() { with(this) {
+      assertBufferEqual( [129, 126, 0, 200, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111], parser.frame("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") )
+    }})
+
+    it("encodes close frames with an error code", function() { with(this) {
+      assertBufferEqual( [0x88, 0x07, 0x03, 0xea, 0x48, 0x65, 0x6c, 0x6c, 0x6f], parser.frame("Hello", "close", 1002) )
+    }})
+
+    it("encodes pong frames", function() { with(this) {
+      assertBufferEqual( [0x8a, 0x00], parser.frame("", "pong") )
+    }})
+  }})
+}})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/runner.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/runner.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/runner.js	(revision 533)
@@ -0,0 +1,54 @@
+require('jsclass')
+
+var WebSocket = require('../lib/faye/websocket'),
+    fs        = require('fs'),
+    http      = require('http'),
+    https     = require('https')
+
+
+JS.ENV.EchoServer = function() {}
+EchoServer.prototype.listen = function(port, ssl) {
+  var server = ssl
+             ? https.createServer({
+                 key:  fs.readFileSync(__dirname + '/server.key'),
+                 cert: fs.readFileSync(__dirname + '/server.crt')
+               })
+             : http.createServer()
+
+  server.addListener('upgrade', function(request, socket, head) {
+    var ws = new WebSocket(request, socket, head, ["echo"])
+    ws.onmessage = function(event) {
+      ws.send(event.data)
+    }
+  })
+  this._httpServer = server
+  server.listen(port)
+}
+EchoServer.prototype.stop = function(callback, scope) {
+  this._httpServer.addListener('close', function() {
+    if (callback) callback.call(scope);
+  });
+  this._httpServer.close();
+}
+
+
+JS.Packages(function() { with(this) {
+  autoload(/.*Spec/, {from: 'spec/faye/websocket'})
+}})
+
+
+JS.require('JS.Test', function() {
+  JS.Test.Unit.Assertions.define("assertBufferEqual", function(array, buffer) {
+    this.assertEqual(array.length, buffer.length);
+    var ary = [], n = buffer.length;
+    while (n--) ary[n] = buffer[n];
+    this.assertEqual(array, ary);
+  })
+
+  JS.require( 'ClientSpec',
+              'Draft75ParserSpec',
+              'Draft76ParserSpec',
+              'HybiParserSpec',
+              JS.Test.method('autorun'))
+})
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/server.crt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/server.crt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/server.crt	(revision 533)
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICZTCCAc4CCQDxyrJZrFA0vjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJV
+SzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBEZh
+eWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJARYRamNvZ2xh
+bkBnbWFpbC5jb20wHhcNMTEwODMwMTIzOTM2WhcNMTIwODI5MTIzOTM2WjB3MQsw
+CQYDVQQGEwJVSzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTAL
+BgNVBAoTBEZheWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJ
+ARYRamNvZ2xhbkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AMDjU5fAK7fvUCZIYHcGXDZD/m9bY+B/UcwGcowk0hMQGYNlLKrpiK7xXBmZpDb6
+r8n+7L/epBeSumbRIm4TDzeNHhuQGYLIeGQy7JNLoPBr6GxubjuJhKOOBnCqcupR
+CLGG7Zw5oL4UvtZVH6kL9XnjyokQQbxxeoV9DqtqOaHHAgMBAAEwDQYJKoZIhvcN
+AQEFBQADgYEAvQjSpzE1ahaeH1CmbLwckTxvWMZfxcZOrxTruK1po3cNnDOjGqFQ
+KEkNj3K5WfwTBD4QgUdYDykhDX2m6HaMz4JEbgrwQv8M8FiswIA3dyGsbOifOk8H
+r3GPNKMzm4o6vrn6RGOpt9q6bsWUBUHfNpP93uU2C9QEwDua3cFjDA0=
+-----END CERTIFICATE-----
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/server.key
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/server.key	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/faye-websocket/spec/server.key	(revision 533)
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDA41OXwCu371AmSGB3Blw2Q/5vW2Pgf1HMBnKMJNITEBmDZSyq
+6Yiu8VwZmaQ2+q/J/uy/3qQXkrpm0SJuEw83jR4bkBmCyHhkMuyTS6Dwa+hsbm47
+iYSjjgZwqnLqUQixhu2cOaC+FL7WVR+pC/V548qJEEG8cXqFfQ6rajmhxwIDAQAB
+AoGABlk1DiCQD8y7mZb2PdSiwlJ4lFewsNnf6lQn/v7TPzdfb5ir4LAxBHkDLACH
+jBuyH3bZefMs+W2l3u5xMKhF7uJqYcUlJdH2UwRfNG54Hn4SGAjQOK3ONer99sUf
+USlsWSX1HjAAFMCBwUfKxMZA3VNQfYKTPdm0jSVf85kHO1ECQQD3s6ksm3QpfD0L
+eG9EoDrqmwnEfpKoWPpz1O0i5tY9VcmhmLwS5Zpd7lB1qjTqzZk4RygU73T/BseJ
+azehIHK5AkEAx1mSXt+ec8RfzVi/io6oqi2vOcACXRbOG4NQmqUWPnumdwsJjsjR
+RzEoDFC2lu6448p9sgEq+CkbmgVeiyp4fwJAQnmgySve/NMuvslPcyddKGD7OhSN
+30ghzrwx98/jZwqC1i9bKeccimDOjwVitjD/Ea9m/ldVGqwDGMoBX+iJYQJAEIOO
+CYfyw1pQKV2huGOq+zX/nwQV7go2lrbhFX55gkGR/6iNaSOfmosq6yJAje5GqLAc
+i4NnQNl+7NpnA5ZIFwJBAI1+OsZyjbRI99pYkTdOpa5IPlIb3j3JbSfjAWHLxlRY
+0HLvN3Q1mE9kbB+uKH6syF/S7nALgsLgq7eHYvIaE/A=
+-----END RSA PRIVATE KEY-----
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+.travis.yml
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/actions/collectable.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/actions/collectable.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/actions/collectable.js	(revision 533)
@@ -0,0 +1,94 @@
+
+var fs = require('fs');
+
+// Collectable Mixin
+//
+// Provides utility methods to read from stdin and remaining arguments.
+var collectable = module.exports;
+
+// XXX: tomdocify, generate in readme
+
+collectable.stdin = function stdin(force, done) {
+  if(!done) done = force, force = false;
+  var argv = this.nopt.argv;
+  var self = this;
+  done = done || function(err) { err && self.emit('error', err); };
+
+  this._readFromStdin = true;
+
+  // not parsed, register done to be read when parse is called
+  if(!argv) {
+    this.once('stdin', done);
+    return this;
+  }
+
+  // only read from stdin when no reamining args and not forced
+  if(!argv.remain.length ||Â force) {
+    this.readStdin(done);
+  }
+
+  return this;
+};
+
+// Read files from remaining args, concat the result and call back the `done`
+// function with the concatanated result and the list of files.
+collectable.files = function files(done) {
+  var argv = this.nopt.argv;
+  var self = this;
+  done = done || function(err) { err && self.emit('error', err); };
+
+  // not parsed, register done to be read when parse is called
+  if(!argv) {
+    this.once('files', done);
+    return this;
+  }
+
+  // only read files when we actually have files to read from
+  if(argv.remain.length) {
+    this.readFiles(argv.remain, done);
+  }
+
+  return this;
+};
+
+collectable.readStdin = function readStdin(done) {
+  var data = '';
+  var self = this;
+  process.stdin.setEncoding('utf8');
+  process.stdin.on('error', done);
+  process.stdin.on('data', function(chunk){
+    data += chunk;
+    self.emit('stdin:data', chunk);
+  }).on('end', function(){
+    self.emit('stdin', null, data);
+    done(null, data);
+  }).resume();
+  return this;
+};
+
+// Asynchronous walk of the remaining args, reading the content and returns
+// the concatanated result.
+collectable.readFiles = function readFiles(filepaths, done) {
+  var data = '';
+  var self = this;
+  var files = filepaths.slice(0);
+  (function read(file) {
+    if(!file) {
+      self.emit('files', null, data, filepaths);
+      return done(null, data, filepaths);
+    }
+    fs.readFile(file, 'utf8', function(err, body) {
+      if(err) return done(err);
+      data += body;
+      self.emit('files:data', body);
+      read(files.shift());
+    });
+  })(files.shift());
+  return this;
+};
+
+// Collect data either from stdin or the list of remaining args
+collectable.collect = function collect(done) {
+  return this.stdin(done).files(done);
+};
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/actions/commandable.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/actions/commandable.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/actions/commandable.js	(revision 533)
@@ -0,0 +1,68 @@
+var nopt = require('nopt');
+
+// Commandable Mixin
+//
+// Provides API to route arbitrary routes or register command / sub commands /
+// sub programs.
+var commandable = module.exports;
+
+// XXX: tomdocify, generate in readme
+
+commandable.cmd =
+commandable.command = function command(name, fn) {
+  this._commands[name] = fn;
+  var commandable = fn && fn.command && fn.route && fn.parse;
+  this.on(name, commandable ? function(args, opts, position) {
+    fn.parse(args, position);
+  } : fn);
+  return this;
+};
+
+commandable.route = function route(pattern, fn) {
+  pattern = pattern instanceof RegExp ? pattern : new RegExp('^' + pattern + '$');
+  this._routes.push({
+    pattern: pattern,
+    fn: fn
+  });
+  return this;
+};
+
+commandable.routeCommand = function routeCommand(opts) {
+  opts = opts || this.nopt;
+  var args = opts.argv.remain;
+  var commands = Object.keys(this._commands);
+
+  // firt try to find a route, then fallback to command
+  var route = this._routes.filter(function(route) {
+    return route.pattern.test(args.join(' '));
+  });
+
+  if(route.length) return route[0].fn();
+
+  var first = 0
+  var registered = args.filter(function(arg, i) {
+    var match = ~commands.indexOf(arg);
+    if(match) first = first || i;
+    return match;
+  });
+
+  if(!registered[0]) return this.run();
+
+  opts.argv.remain = args.slice(0, first);
+  registered.forEach(function(command) {
+    var position = opts.argv.original.indexOf(command) + 1;
+    var options = nopt({}, {}, opts.argv.original, position);
+    this.emit(command, options.argv.original, options, position);
+  }, this);
+};
+
+
+commandable.registered = function(args) {
+  var commands = Object.keys(this._commands);
+  var registered = args.filter(function(arg, i) {
+    return ~commands.indexOf(arg);
+  });
+
+  return registered.length ? this._commands[registered] : false;
+};
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/index.js	(revision 533)
@@ -0,0 +1,253 @@
+
+var fs     = require('fs');
+var path   = require('path');
+var nopt   = require('nopt');
+var util   = require('./util');
+var events = require('events');
+
+var collectable = require('./actions/collectable');
+var commandable = require('./actions/commandable');
+
+module.exports = noptify;
+noptify.Noptify = Noptify;
+
+// noptify is a little wrapper around `nopt` module adding a more expressive,
+// commander-like, API and few helpers.
+//
+// Examples
+//
+//     var program = noptify(process.argv, { program: 'name' })
+//       .version('0.0.1')
+//       .option('port', '-p', 'Port to listen on (default: 35729)', Number)
+//       .option('pid', 'Path to the generated PID file', String)
+//
+//     var opts = program.parse();
+//
+// Returns an instance of `Noptify`
+function noptify(args, options) {
+  return new Noptify(args, options);
+}
+
+// Noptify provides the API to parse out option, shorthands and generate the
+// proper generic help output.
+//
+// - args     - The Array of arguments to parse (default: `process.argv`);
+// - options  - An hash of options with the following properties
+//  - program - The program name to use in usage output
+//
+// Every noptify instance is created with two options, `-h, --help` and `-v,
+// --version`.
+function Noptify(args, options) {
+  events.EventEmitter.call(this);
+  options = this.options = options || {};
+  this.args = args || process.argv;
+  this._program = options.program || (path.basename(this.args[this.args[0] === 'node' ? 1 : 0]));
+
+  this._shorthands = {};
+  this._commands = {};
+  this._routes = [];
+  this._steps = [];
+  this.nopt = {};
+
+  this.option('help', '-h', 'Show help usage');
+  this.option('version', '-v', 'Show package version');
+}
+
+util.inherits(Noptify, events.EventEmitter);
+
+// Inherits from each actions' mixins
+//
+// XXX: consider making it optional? with a `.use()` method?
+util.extend(Noptify.prototype, collectable);
+util.extend(Noptify.prototype, commandable);
+
+
+// Parse the provided options and shorthands, pass them through `nopt` and
+// return the result.
+//
+// When `opts.help` is set, the help output is displayed and `help`
+// event is emitted. The process exists with `0` status, the help output is
+// automatically displayed and the `help` event is emitted.
+//
+// Examples
+//
+//    var program = noptify(['foo', '--help'])
+//      .on('help', function() {
+//        console.log('Examples');
+//        console.log('');
+//        console.log('  foo bar --baz > foo.txt');
+//      });
+//
+//    var opts = program.parse();
+//    // ... Help output ...
+//    // ... Custom help output ...
+//    // ... Exit ...
+//
+//
+Noptify.prototype.parse = function parse(argv, position) {
+  argv = argv ||Â this.args;
+  var options = this._options.reduce(function(opts, opt) {
+    opts[opt.name] = opt.type;
+    return opts;
+  }, {});
+
+  this._options.forEach(function(opt) {
+    if(!opt.shorthand) return;
+    this.shorthand(opt.shorthand, '--' + opt.name);
+  }, this);
+
+  var opts = nopt(options, this._shorthands, argv, position);
+  if(opts.version) {
+    console.log(this._version);
+    process.exit(0);
+  }
+
+  var registered = this.registered(opts.argv.remain);
+  if(opts.help) {
+    if(registered && registered.help) {
+      registered.help().emit('help');
+    } else {
+      this.help().emit('help');
+    }
+
+    process.exit(0);
+  }
+
+  this.nopt = opts;
+
+  // check remaining args and registered command, for each match, remove the
+  // argument from remaining args and trigger the handler, ideally the handler
+  // can be another subprogram, for now simple functions
+
+  if(this.routeCommand) process.nextTick(this.routeCommand.bind(this));
+  if(this.stdin && this._readFromStdin) process.nextTick(this.stdin.bind(this));
+  return opts;
+};
+
+// Define the program version.
+Noptify.prototype.version = function version(ver) {
+  this._version = ver;
+  return this;
+};
+
+// Define the program property.
+Noptify.prototype.program = function program(value) {
+  this._program = value || '';
+  return this;
+};
+
+// Define `name` option with optional shorthands, optional description and optional type.
+Noptify.prototype.option = function option(name, shorthand, description, type) {
+  this._options = this._options || [];
+  if(!description) {
+    description = shorthand;
+    shorthand = '';
+  }
+
+  if(!type) {
+    if(typeof description === 'function') {
+      type = description;
+      description = shorthand;
+      shorthand = '';
+    } else {
+      type = String;
+    }
+  }
+
+  shorthand = shorthand.replace(/^-*/, ''),
+
+  this._options.push({
+    name: name,
+    shorthand: shorthand.replace(/^-*/, ''),
+    description: description ||Â (name + ': ' + type.name),
+    usage: (shorthand ? '-' + shorthand + ', ': '' ) + '--' + name,
+    type: type
+  });
+
+  return this;
+};
+
+// Stores the given `shorthands` Hash of options to be `parse()`-d by nopt
+// later on.
+
+Noptify.prototype.shorthand =
+Noptify.prototype.shorthands = function shorthands(options, value) {
+  if(typeof options === 'string' && value) {
+    this._shorthands[options] = value;
+    return this;
+  }
+
+  Object.keys(options).forEach(function(shorthand) {
+    this._shorthands[shorthand] = options[shorthand];
+  }, this);
+  return this;
+};
+
+// Simply output to stdout the Usage and Help output.
+Noptify.prototype.help = function help() {
+  var buf = '';
+  buf += '\n  Usage: ' + this._program + ' [options]';
+  buf += '\n';
+  buf += '\n  Options:\n';
+
+  var maxln = Math.max.apply(Math, this._options.map(function(opts) {
+    return opts.usage.length;
+  }));
+
+  var options = this._options.map(function(opts) {
+    return '    ' + pad(opts.usage, maxln + 5) + '\t- ' + opts.description;
+  });
+
+  buf += options.join('\n');
+
+  // part of help input ? --list-shorthands ?
+  var shorthands = Object.keys(this._shorthands);
+  if(shorthands.length) {
+    buf += '\n\n  Shorthands:\n';
+    maxln = Math.max.apply(Math, Object.keys(this._shorthands).map(function(key) {
+      return key.length;
+    }));
+    buf += Object.keys(this._shorthands).map(function(shorthand) {
+      return '    --' + pad(shorthand, maxln + 1) + '\t\t' + this._shorthands[shorthand];
+    }, this).join('\n');
+  }
+
+  buf += '\n';
+
+  console.log(buf);
+  return this;
+};
+
+// Helpers
+
+// command API
+
+Noptify.prototype.run = function run(fn) {
+  if(fn) {
+    this._steps.push(fn);
+    return this;
+  }
+
+  if(!this.nopt.argv) return this.parse();
+
+  var steps = this._steps;
+  var self = this;
+  (function next(step) {
+    if(!step) return;
+    var async = /function\s*\(\w+/.test(step + '');
+    if(!async) {
+      step();
+      return next(steps.shift());
+    }
+
+    step(function(err) {
+      if(err) return self.emit('error', err);
+      next(steps.shift());
+    });
+  })(steps.shift());
+};
+
+function pad(str, max) {
+  var ln = max - str.length;
+  return ln > 0 ? str + new Array(ln).join(' ') : str;
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/.bin/nopt
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/.bin/nopt	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/.bin/nopt	(revision 533)
@@ -0,0 +1,1 @@
+link ../nopt/bin/nopt.js
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/LICENSE	(revision 533)
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+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 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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/README.md	(revision 533)
@@ -0,0 +1,210 @@
+If you want to write an option parser, and have it be good, there are
+two ways to do it.  The Right Way, and the Wrong Way.
+
+The Wrong Way is to sit down and write an option parser.  We've all done
+that.
+
+The Right Way is to write some complex configurable program with so many
+options that you go half-insane just trying to manage them all, and put
+it off with duct-tape solutions until you see exactly to the core of the
+problem, and finally snap and write an awesome option parser.
+
+If you want to write an option parser, don't write an option parser.
+Write a package manager, or a source control system, or a service
+restarter, or an operating system.  You probably won't end up with a
+good one of those, but if you don't give up, and you are relentless and
+diligent enough in your procrastination, you may just end up with a very
+nice option parser.
+
+## USAGE
+
+    // my-program.js
+    var nopt = require("nopt")
+      , Stream = require("stream").Stream
+      , path = require("path")
+      , knownOpts = { "foo" : [String, null]
+                    , "bar" : [Stream, Number]
+                    , "baz" : path
+                    , "bloo" : [ "big", "medium", "small" ]
+                    , "flag" : Boolean
+                    , "pick" : Boolean
+                    , "many" : [String, Array]
+                    }
+      , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
+                     , "b7" : ["--bar", "7"]
+                     , "m" : ["--bloo", "medium"]
+                     , "p" : ["--pick"]
+                     , "f" : ["--flag"]
+                     }
+                 // everything is optional.
+                 // knownOpts and shorthands default to {}
+                 // arg list defaults to process.argv
+                 // slice defaults to 2
+      , parsed = nopt(knownOpts, shortHands, process.argv, 2)
+    console.log(parsed)
+
+This would give you support for any of the following:
+
+```bash
+$ node my-program.js --foo "blerp" --no-flag
+{ "foo" : "blerp", "flag" : false }
+
+$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag
+{ bar: 7, foo: "Mr. Hand", flag: true }
+
+$ node my-program.js --foo "blerp" -f -----p
+{ foo: "blerp", flag: true, pick: true }
+
+$ node my-program.js -fp --foofoo
+{ foo: "Mr. Foo", flag: true, pick: true }
+
+$ node my-program.js --foofoo -- -fp  # -- stops the flag parsing.
+{ foo: "Mr. Foo", argv: { remain: ["-fp"] } }
+
+$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.
+{ blatzk: 1000, flag: true, pick: true }
+
+$ node my-program.js --blatzk true -fp # but they need a value
+{ blatzk: true, flag: true, pick: true }
+
+$ node my-program.js --no-blatzk -fp # unless they start with "no-"
+{ blatzk: false, flag: true, pick: true }
+
+$ node my-program.js --baz b/a/z # known paths are resolved.
+{ baz: "/Users/isaacs/b/a/z" }
+
+# if Array is one of the types, then it can take many
+# values, and will always be an array.  The other types provided
+# specify what types are allowed in the list.
+
+$ node my-program.js --many 1 --many null --many foo
+{ many: ["1", "null", "foo"] }
+
+$ node my-program.js --many foo
+{ many: ["foo"] }
+```
+
+Read the tests at the bottom of `lib/nopt.js` for more examples of
+what this puppy can do.
+
+## Types
+
+The following types are supported, and defined on `nopt.typeDefs`
+
+* String: A normal string.  No parsing is done.
+* path: A file system path.  Gets resolved against cwd if not absolute.
+* url: A url.  If it doesn't parse, it isn't accepted.
+* Number: Must be numeric.
+* Date: Must parse as a date. If it does, and `Date` is one of the options,
+  then it will return a Date object, not a string.
+* Boolean: Must be either `true` or `false`.  If an option is a boolean,
+  then it does not need a value, and its presence will imply `true` as
+  the value.  To negate boolean flags, do `--no-whatever` or `--whatever
+  false`
+* NaN: Means that the option is strictly not allowed.  Any value will
+  fail.
+* Stream: An object matching the "Stream" class in node.  Valuable
+  for use when validating programmatically.  (npm uses this to let you
+  supply any WriteStream on the `outfd` and `logfd` config options.)
+* Array: If `Array` is specified as one of the types, then the value
+  will be parsed as a list of options.  This means that multiple values
+  can be specified, and that the value will always be an array.
+
+If a type is an array of values not on this list, then those are
+considered valid values.  For instance, in the example above, the
+`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`,
+and any other value will be rejected.
+
+When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be
+interpreted as their JavaScript equivalents, and numeric values will be
+interpreted as a number.
+
+You can also mix types and values, or multiple types, in a list.  For
+instance `{ blah: [Number, null] }` would allow a value to be set to
+either a Number or null.  When types are ordered, this implies a
+preference, and the first type that can be used to properly interpret
+the value will be used.
+
+To define a new type, add it to `nopt.typeDefs`.  Each item in that
+hash is an object with a `type` member and a `validate` method.  The
+`type` member is an object that matches what goes in the type list.  The
+`validate` method is a function that gets called with `validate(data,
+key, val)`.  Validate methods should assign `data[key]` to the valid
+value of `val` if it can be handled properly, or return boolean
+`false` if it cannot.
+
+You can also call `nopt.clean(data, types, typeDefs)` to clean up a
+config object and remove its invalid properties.
+
+## Error Handling
+
+By default, nopt outputs a warning to standard error when invalid
+options are found.  You can change this behavior by assigning a method
+to `nopt.invalidHandler`.  This method will be called with
+the offending `nopt.invalidHandler(key, val, types)`.
+
+If no `nopt.invalidHandler` is assigned, then it will console.error
+its whining.  If it is assigned to boolean `false` then the warning is
+suppressed.
+
+## Abbreviations
+
+Yes, they are supported.  If you define options like this:
+
+```javascript
+{ "foolhardyelephants" : Boolean
+, "pileofmonkeys" : Boolean }
+```
+
+Then this will work:
+
+```bash
+node program.js --foolhar --pil
+node program.js --no-f --pileofmon
+# etc.
+```
+
+## Shorthands
+
+Shorthands are a hash of shorter option names to a snippet of args that
+they expand to.
+
+If multiple one-character shorthands are all combined, and the
+combination does not unambiguously match any other option or shorthand,
+then they will be broken up into their constituent parts.  For example:
+
+```json
+{ "s" : ["--loglevel", "silent"]
+, "g" : "--global"
+, "f" : "--force"
+, "p" : "--parseable"
+, "l" : "--long"
+}
+```
+
+```bash
+npm ls -sgflp
+# just like doing this:
+npm ls --loglevel silent --global --force --long --parseable
+```
+
+## The Rest of the args
+
+The config object returned by nopt is given a special member called
+`argv`, which is an object with the following fields:
+
+* `remain`: The remaining args after all the parsing has occurred.
+* `original`: The args as they originally appeared.
+* `cooked`: The args after flags and shorthands are expanded.
+
+## Slicing
+
+Node programs are called with more or less the exact argv as it appears
+in C land, after the v8 and node-specific options have been plucked off.
+As such, `argv[0]` is always `node` and `argv[1]` is always the
+JavaScript program being run.
+
+That's usually not very useful to you.  So they're sliced off by
+default.  If you want them, then you can pass in `0` as the last
+argument, or any other number that you'd like to slice off the start of
+the list.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/bin/nopt.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/bin/nopt.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/bin/nopt.js	(revision 533)
@@ -0,0 +1,44 @@
+#!/usr/bin/env node
+var nopt = require("../lib/nopt")
+  , types = { num: Number
+            , bool: Boolean
+            , help: Boolean
+            , list: Array
+            , "num-list": [Number, Array]
+            , "str-list": [String, Array]
+            , "bool-list": [Boolean, Array]
+            , str: String }
+  , shorthands = { s: [ "--str", "astring" ]
+                 , b: [ "--bool" ]
+                 , nb: [ "--no-bool" ]
+                 , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ]
+                 , "?": ["--help"]
+                 , h: ["--help"]
+                 , H: ["--help"]
+                 , n: [ "--num", "125" ] }
+  , parsed = nopt( types
+                 , shorthands
+                 , process.argv
+                 , 2 )
+
+console.log("parsed", parsed)
+
+if (parsed.help) {
+  console.log("")
+  console.log("nopt cli tester")
+  console.log("")
+  console.log("types")
+  console.log(Object.keys(types).map(function M (t) {
+    var type = types[t]
+    if (Array.isArray(type)) {
+      return [t, type.map(function (type) { return type.name })]
+    }
+    return [t, type && type.name]
+  }).reduce(function (s, i) {
+    s[i[0]] = i[1]
+    return s
+  }, {}))
+  console.log("")
+  console.log("shorthands")
+  console.log(shorthands)
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/examples/my-program.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/examples/my-program.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/examples/my-program.js	(revision 533)
@@ -0,0 +1,30 @@
+#!/usr/bin/env node
+
+//process.env.DEBUG_NOPT = 1
+
+// my-program.js
+var nopt = require("../lib/nopt")
+  , Stream = require("stream").Stream
+  , path = require("path")
+  , knownOpts = { "foo" : [String, null]
+                , "bar" : [Stream, Number]
+                , "baz" : path
+                , "bloo" : [ "big", "medium", "small" ]
+                , "flag" : Boolean
+                , "pick" : Boolean
+                }
+  , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
+                 , "b7" : ["--bar", "7"]
+                 , "m" : ["--bloo", "medium"]
+                 , "p" : ["--pick"]
+                 , "f" : ["--flag", "true"]
+                 , "g" : ["--flag"]
+                 , "s" : "--flag"
+                 }
+             // everything is optional.
+             // knownOpts and shorthands default to {}
+             // arg list defaults to process.argv
+             // slice defaults to 2
+  , parsed = nopt(knownOpts, shortHands, process.argv, 2)
+
+console.log("parsed =\n"+ require("util").inspect(parsed))
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/lib/nopt.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/lib/nopt.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/lib/nopt.js	(revision 533)
@@ -0,0 +1,555 @@
+// info about each config option.
+
+var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG
+  ? function () { console.error.apply(console, arguments) }
+  : function () {}
+
+var url = require("url")
+  , path = require("path")
+  , Stream = require("stream").Stream
+  , abbrev = require("abbrev")
+
+module.exports = exports = nopt
+exports.clean = clean
+
+exports.typeDefs =
+  { String  : { type: String,  validate: validateString  }
+  , Boolean : { type: Boolean, validate: validateBoolean }
+  , url     : { type: url,     validate: validateUrl     }
+  , Number  : { type: Number,  validate: validateNumber  }
+  , path    : { type: path,    validate: validatePath    }
+  , Stream  : { type: Stream,  validate: validateStream  }
+  , Date    : { type: Date,    validate: validateDate    }
+  }
+
+function nopt (types, shorthands, args, slice) {
+  args = args || process.argv
+  types = types || {}
+  shorthands = shorthands || {}
+  if (typeof slice !== "number") slice = 2
+
+  debug(types, shorthands, args, slice)
+
+  args = args.slice(slice)
+  var data = {}
+    , key
+    , remain = []
+    , cooked = args
+    , original = args.slice(0)
+
+  parse(args, data, remain, types, shorthands)
+  // now data is full
+  clean(data, types, exports.typeDefs)
+  data.argv = {remain:remain,cooked:cooked,original:original}
+  Object.defineProperty(data.argv, 'toString', { value: function () {
+    return this.original.map(JSON.stringify).join(" ")
+  }, enumerable: false })
+  return data
+}
+
+function clean (data, types, typeDefs) {
+  typeDefs = typeDefs || exports.typeDefs
+  var remove = {}
+    , typeDefault = [false, true, null, String, Number]
+
+  Object.keys(data).forEach(function (k) {
+    if (k === "argv") return
+    var val = data[k]
+      , isArray = Array.isArray(val)
+      , type = types[k]
+    if (!isArray) val = [val]
+    if (!type) type = typeDefault
+    if (type === Array) type = typeDefault.concat(Array)
+    if (!Array.isArray(type)) type = [type]
+
+    debug("val=%j", val)
+    debug("types=", type)
+    val = val.map(function (val) {
+      // if it's an unknown value, then parse false/true/null/numbers/dates
+      if (typeof val === "string") {
+        debug("string %j", val)
+        val = val.trim()
+        if ((val === "null" && ~type.indexOf(null))
+            || (val === "true" &&
+               (~type.indexOf(true) || ~type.indexOf(Boolean)))
+            || (val === "false" &&
+               (~type.indexOf(false) || ~type.indexOf(Boolean)))) {
+          val = JSON.parse(val)
+          debug("jsonable %j", val)
+        } else if (~type.indexOf(Number) && !isNaN(val)) {
+          debug("convert to number", val)
+          val = +val
+        } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) {
+          debug("convert to date", val)
+          val = new Date(val)
+        }
+      }
+
+      if (!types.hasOwnProperty(k)) {
+        return val
+      }
+
+      // allow `--no-blah` to set 'blah' to null if null is allowed
+      if (val === false && ~type.indexOf(null) &&
+          !(~type.indexOf(false) || ~type.indexOf(Boolean))) {
+        val = null
+      }
+
+      var d = {}
+      d[k] = val
+      debug("prevalidated val", d, val, types[k])
+      if (!validate(d, k, val, types[k], typeDefs)) {
+        if (exports.invalidHandler) {
+          exports.invalidHandler(k, val, types[k], data)
+        } else if (exports.invalidHandler !== false) {
+          debug("invalid: "+k+"="+val, types[k])
+        }
+        return remove
+      }
+      debug("validated val", d, val, types[k])
+      return d[k]
+    }).filter(function (val) { return val !== remove })
+
+    if (!val.length) delete data[k]
+    else if (isArray) {
+      debug(isArray, data[k], val)
+      data[k] = val
+    } else data[k] = val[0]
+
+    debug("k=%s val=%j", k, val, data[k])
+  })
+}
+
+function validateString (data, k, val) {
+  data[k] = String(val)
+}
+
+function validatePath (data, k, val) {
+  data[k] = path.resolve(String(val))
+  return true
+}
+
+function validateNumber (data, k, val) {
+  debug("validate Number %j %j %j", k, val, isNaN(val))
+  if (isNaN(val)) return false
+  data[k] = +val
+}
+
+function validateDate (data, k, val) {
+  debug("validate Date %j %j %j", k, val, Date.parse(val))
+  var s = Date.parse(val)
+  if (isNaN(s)) return false
+  data[k] = new Date(val)
+}
+
+function validateBoolean (data, k, val) {
+  if (val instanceof Boolean) val = val.valueOf()
+  else if (typeof val === "string") {
+    if (!isNaN(val)) val = !!(+val)
+    else if (val === "null" || val === "false") val = false
+    else val = true
+  } else val = !!val
+  data[k] = val
+}
+
+function validateUrl (data, k, val) {
+  val = url.parse(String(val))
+  if (!val.host) return false
+  data[k] = val.href
+}
+
+function validateStream (data, k, val) {
+  if (!(val instanceof Stream)) return false
+  data[k] = val
+}
+
+function validate (data, k, val, type, typeDefs) {
+  // arrays are lists of types.
+  if (Array.isArray(type)) {
+    for (var i = 0, l = type.length; i < l; i ++) {
+      if (type[i] === Array) continue
+      if (validate(data, k, val, type[i], typeDefs)) return true
+    }
+    delete data[k]
+    return false
+  }
+
+  // an array of anything?
+  if (type === Array) return true
+
+  // NaN is poisonous.  Means that something is not allowed.
+  if (type !== type) {
+    debug("Poison NaN", k, val, type)
+    delete data[k]
+    return false
+  }
+
+  // explicit list of values
+  if (val === type) {
+    debug("Explicitly allowed %j", val)
+    // if (isArray) (data[k] = data[k] || []).push(val)
+    // else data[k] = val
+    data[k] = val
+    return true
+  }
+
+  // now go through the list of typeDefs, validate against each one.
+  var ok = false
+    , types = Object.keys(typeDefs)
+  for (var i = 0, l = types.length; i < l; i ++) {
+    debug("test type %j %j %j", k, val, types[i])
+    var t = typeDefs[types[i]]
+    if (t && type === t.type) {
+      var d = {}
+      ok = false !== t.validate(d, k, val)
+      val = d[k]
+      if (ok) {
+        // if (isArray) (data[k] = data[k] || []).push(val)
+        // else data[k] = val
+        data[k] = val
+        break
+      }
+    }
+  }
+  debug("OK? %j (%j %j %j)", ok, k, val, types[i])
+
+  if (!ok) delete data[k]
+  return ok
+}
+
+function parse (args, data, remain, types, shorthands) {
+  debug("parse", args, data, remain)
+
+  var key = null
+    , abbrevs = abbrev(Object.keys(types))
+    , shortAbbr = abbrev(Object.keys(shorthands))
+
+  for (var i = 0; i < args.length; i ++) {
+    var arg = args[i]
+    debug("arg", arg)
+
+    if (arg.match(/^-{2,}$/)) {
+      // done with keys.
+      // the rest are args.
+      remain.push.apply(remain, args.slice(i + 1))
+      args[i] = "--"
+      break
+    }
+    var hadEq = false
+    if (arg.charAt(0) === "-") {
+      if (arg.indexOf("=") !== -1) {
+        hadEq = true
+        var v = arg.split("=")
+        arg = v.shift()
+        v = v.join("=")
+        args.splice.apply(args, [i, 1].concat([arg, v]))
+      }
+      // see if it's a shorthand
+      // if so, splice and back up to re-parse it.
+      var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs)
+      debug("arg=%j shRes=%j", arg, shRes)
+      if (shRes) {
+        debug(arg, shRes)
+        args.splice.apply(args, [i, 1].concat(shRes))
+        if (arg !== shRes[0]) {
+          i --
+          continue
+        }
+      }
+      arg = arg.replace(/^-+/, "")
+      var no = null
+      while (arg.toLowerCase().indexOf("no-") === 0) {
+        no = !no
+        arg = arg.substr(3)
+      }
+
+      if (abbrevs[arg]) arg = abbrevs[arg]
+
+      var isArray = types[arg] === Array ||
+        Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1
+
+      var val
+        , la = args[i + 1]
+
+      var isBool = typeof no === 'boolean' ||
+        types[arg] === Boolean ||
+        Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 ||
+        (typeof types[arg] === 'undefined' && !hadEq) ||
+        (la === "false" &&
+         (types[arg] === null ||
+          Array.isArray(types[arg]) && ~types[arg].indexOf(null)))
+
+      if (isBool) {
+        // just set and move along
+        val = !no
+        // however, also support --bool true or --bool false
+        if (la === "true" || la === "false") {
+          val = JSON.parse(la)
+          la = null
+          if (no) val = !val
+          i ++
+        }
+
+        // also support "foo":[Boolean, "bar"] and "--foo bar"
+        if (Array.isArray(types[arg]) && la) {
+          if (~types[arg].indexOf(la)) {
+            // an explicit type
+            val = la
+            i ++
+          } else if ( la === "null" && ~types[arg].indexOf(null) ) {
+            // null allowed
+            val = null
+            i ++
+          } else if ( !la.match(/^-{2,}[^-]/) &&
+                      !isNaN(la) &&
+                      ~types[arg].indexOf(Number) ) {
+            // number
+            val = +la
+            i ++
+          } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) {
+            // string
+            val = la
+            i ++
+          }
+        }
+
+        if (isArray) (data[arg] = data[arg] || []).push(val)
+        else data[arg] = val
+
+        continue
+      }
+
+      if (la && la.match(/^-{2,}$/)) {
+        la = undefined
+        i --
+      }
+
+      val = la === undefined ? true : la
+      if (isArray) (data[arg] = data[arg] || []).push(val)
+      else data[arg] = val
+
+      i ++
+      continue
+    }
+    remain.push(arg)
+  }
+}
+
+function resolveShort (arg, shorthands, shortAbbr, abbrevs) {
+  // handle single-char shorthands glommed together, like
+  // npm ls -glp, but only if there is one dash, and only if
+  // all of the chars are single-char shorthands, and it's
+  // not a match to some other abbrev.
+  arg = arg.replace(/^-+/, '')
+  if (abbrevs[arg] && !shorthands[arg]) {
+    return null
+  }
+  if (shortAbbr[arg]) {
+    arg = shortAbbr[arg]
+  } else {
+    var singles = shorthands.___singles
+    if (!singles) {
+      singles = Object.keys(shorthands).filter(function (s) {
+        return s.length === 1
+      }).reduce(function (l,r) { l[r] = true ; return l }, {})
+      shorthands.___singles = singles
+    }
+    var chrs = arg.split("").filter(function (c) {
+      return singles[c]
+    })
+    if (chrs.join("") === arg) return chrs.map(function (c) {
+      return shorthands[c]
+    }).reduce(function (l, r) {
+      return l.concat(r)
+    }, [])
+  }
+
+  if (shorthands[arg] && !Array.isArray(shorthands[arg])) {
+    shorthands[arg] = shorthands[arg].split(/\s+/)
+  }
+  return shorthands[arg]
+}
+
+if (module === require.main) {
+var assert = require("assert")
+  , util = require("util")
+
+  , shorthands =
+    { s : ["--loglevel", "silent"]
+    , d : ["--loglevel", "info"]
+    , dd : ["--loglevel", "verbose"]
+    , ddd : ["--loglevel", "silly"]
+    , noreg : ["--no-registry"]
+    , reg : ["--registry"]
+    , "no-reg" : ["--no-registry"]
+    , silent : ["--loglevel", "silent"]
+    , verbose : ["--loglevel", "verbose"]
+    , h : ["--usage"]
+    , H : ["--usage"]
+    , "?" : ["--usage"]
+    , help : ["--usage"]
+    , v : ["--version"]
+    , f : ["--force"]
+    , desc : ["--description"]
+    , "no-desc" : ["--no-description"]
+    , "local" : ["--no-global"]
+    , l : ["--long"]
+    , p : ["--parseable"]
+    , porcelain : ["--parseable"]
+    , g : ["--global"]
+    }
+
+  , types =
+    { aoa: Array
+    , nullstream: [null, Stream]
+    , date: Date
+    , str: String
+    , browser : String
+    , cache : path
+    , color : ["always", Boolean]
+    , depth : Number
+    , description : Boolean
+    , dev : Boolean
+    , editor : path
+    , force : Boolean
+    , global : Boolean
+    , globalconfig : path
+    , group : [String, Number]
+    , gzipbin : String
+    , logfd : [Number, Stream]
+    , loglevel : ["silent","win","error","warn","info","verbose","silly"]
+    , long : Boolean
+    , "node-version" : [false, String]
+    , npaturl : url
+    , npat : Boolean
+    , "onload-script" : [false, String]
+    , outfd : [Number, Stream]
+    , parseable : Boolean
+    , pre: Boolean
+    , prefix: path
+    , proxy : url
+    , "rebuild-bundle" : Boolean
+    , registry : url
+    , searchopts : String
+    , searchexclude: [null, String]
+    , shell : path
+    , t: [Array, String]
+    , tag : String
+    , tar : String
+    , tmp : path
+    , "unsafe-perm" : Boolean
+    , usage : Boolean
+    , user : String
+    , username : String
+    , userconfig : path
+    , version : Boolean
+    , viewer: path
+    , _exit : Boolean
+    }
+
+; [["-v", {version:true}, []]
+  ,["---v", {version:true}, []]
+  ,["ls -s --no-reg connect -d",
+    {loglevel:"info",registry:null},["ls","connect"]]
+  ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]]
+  ,["ls --registry blargle", {}, ["ls"]]
+  ,["--no-registry", {registry:null}, []]
+  ,["--no-color true", {color:false}, []]
+  ,["--no-color false", {color:true}, []]
+  ,["--no-color", {color:false}, []]
+  ,["--color false", {color:false}, []]
+  ,["--color --logfd 7", {logfd:7,color:true}, []]
+  ,["--color=true", {color:true}, []]
+  ,["--logfd=10", {logfd:10}, []]
+  ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]]
+  ,["--tmp=tmp -tar=gtar",
+    {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]]
+  ,["--logfd x", {}, []]
+  ,["a -true -- -no-false", {true:true},["a","-no-false"]]
+  ,["a -no-false", {false:false},["a"]]
+  ,["a -no-no-true", {true:true}, ["a"]]
+  ,["a -no-no-no-false", {false:false}, ["a"]]
+  ,["---NO-no-No-no-no-no-nO-no-no"+
+    "-No-no-no-no-no-no-no-no-no"+
+    "-no-no-no-no-NO-NO-no-no-no-no-no-no"+
+    "-no-body-can-do-the-boogaloo-like-I-do"
+   ,{"body-can-do-the-boogaloo-like-I-do":false}, []]
+  ,["we are -no-strangers-to-love "+
+    "--you-know=the-rules --and=so-do-i "+
+    "---im-thinking-of=a-full-commitment "+
+    "--no-you-would-get-this-from-any-other-guy "+
+    "--no-gonna-give-you-up "+
+    "-no-gonna-let-you-down=true "+
+    "--no-no-gonna-run-around false "+
+    "--desert-you=false "+
+    "--make-you-cry false "+
+    "--no-tell-a-lie "+
+    "--no-no-and-hurt-you false"
+   ,{"strangers-to-love":false
+    ,"you-know":"the-rules"
+    ,"and":"so-do-i"
+    ,"you-would-get-this-from-any-other-guy":false
+    ,"gonna-give-you-up":false
+    ,"gonna-let-you-down":false
+    ,"gonna-run-around":false
+    ,"desert-you":false
+    ,"make-you-cry":false
+    ,"tell-a-lie":false
+    ,"and-hurt-you":false
+    },["we", "are"]]
+  ,["-t one -t two -t three"
+   ,{t: ["one", "two", "three"]}
+   ,[]]
+  ,["-t one -t null -t three four five null"
+   ,{t: ["one", "null", "three"]}
+   ,["four", "five", "null"]]
+  ,["-t foo"
+   ,{t:["foo"]}
+   ,[]]
+  ,["--no-t"
+   ,{t:["false"]}
+   ,[]]
+  ,["-no-no-t"
+   ,{t:["true"]}
+   ,[]]
+  ,["-aoa one -aoa null -aoa 100"
+   ,{aoa:["one", null, 100]}
+   ,[]]
+  ,["-str 100"
+   ,{str:"100"}
+   ,[]]
+  ,["--color always"
+   ,{color:"always"}
+   ,[]]
+  ,["--no-nullstream"
+   ,{nullstream:null}
+   ,[]]
+  ,["--nullstream false"
+   ,{nullstream:null}
+   ,[]]
+  ,["--notadate=2011-01-25"
+   ,{notadate: "2011-01-25"}
+   ,[]]
+  ,["--date 2011-01-25"
+   ,{date: new Date("2011-01-25")}
+   ,[]]
+  ].forEach(function (test) {
+    var argv = test[0].split(/\s+/)
+      , opts = test[1]
+      , rem = test[2]
+      , actual = nopt(types, shorthands, argv, 0)
+      , parsed = actual.argv
+    delete actual.argv
+    console.log(util.inspect(actual, false, 2, true), parsed.remain)
+    for (var i in opts) {
+      var e = JSON.stringify(opts[i])
+        , a = JSON.stringify(actual[i] === undefined ? null : actual[i])
+      if (e && typeof e === "object") {
+        assert.deepEqual(e, a)
+      } else {
+        assert.equal(e, a)
+      }
+    }
+    assert.deepEqual(rem, parsed.remain)
+  })
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md	(revision 533)
@@ -0,0 +1,3 @@
+ To get started, <a
+ href="http://www.clahub.com/agreements/isaacs/abbrev-js">sign the
+ Contributor License Agreement</a>.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE	(revision 533)
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+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 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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md	(revision 533)
@@ -0,0 +1,23 @@
+# abbrev-js
+
+Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
+
+Usage:
+
+    var abbrev = require("abbrev");
+    abbrev("foo", "fool", "folding", "flop");
+    
+    // returns:
+    { fl: 'flop'
+    , flo: 'flop'
+    , flop: 'flop'
+    , fol: 'folding'
+    , fold: 'folding'
+    , foldi: 'folding'
+    , foldin: 'folding'
+    , folding: 'folding'
+    , foo: 'foo'
+    , fool: 'fool'
+    }
+
+This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/abbrev.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/abbrev.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/abbrev.js	(revision 533)
@@ -0,0 +1,62 @@
+
+module.exports = exports = abbrev.abbrev = abbrev
+
+abbrev.monkeyPatch = monkeyPatch
+
+function monkeyPatch () {
+  Object.defineProperty(Array.prototype, 'abbrev', {
+    value: function () { return abbrev(this) },
+    enumerable: false, configurable: true, writable: true
+  })
+
+  Object.defineProperty(Object.prototype, 'abbrev', {
+    value: function () { return abbrev(Object.keys(this)) },
+    enumerable: false, configurable: true, writable: true
+  })
+}
+
+function abbrev (list) {
+  if (arguments.length !== 1 || !Array.isArray(list)) {
+    list = Array.prototype.slice.call(arguments, 0)
+  }
+  for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
+    args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
+  }
+
+  // sort them lexicographically, so that they're next to their nearest kin
+  args = args.sort(lexSort)
+
+  // walk through each, seeing how much it has in common with the next and previous
+  var abbrevs = {}
+    , prev = ""
+  for (var i = 0, l = args.length ; i < l ; i ++) {
+    var current = args[i]
+      , next = args[i + 1] || ""
+      , nextMatches = true
+      , prevMatches = true
+    if (current === next) continue
+    for (var j = 0, cl = current.length ; j < cl ; j ++) {
+      var curChar = current.charAt(j)
+      nextMatches = nextMatches && curChar === next.charAt(j)
+      prevMatches = prevMatches && curChar === prev.charAt(j)
+      if (!nextMatches && !prevMatches) {
+        j ++
+        break
+      }
+    }
+    prev = current
+    if (j === cl) {
+      abbrevs[current] = current
+      continue
+    }
+    for (var a = current.substr(0, j) ; j <= cl ; j ++) {
+      abbrevs[a] = current
+      a += current.charAt(j)
+    }
+  }
+  return abbrevs
+}
+
+function lexSort (a, b) {
+  return a === b ? 0 : a > b ? 1 : -1
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json	(revision 533)
@@ -0,0 +1,33 @@
+{
+  "name": "abbrev",
+  "version": "1.0.5",
+  "description": "Like ruby's abbrev module, but in js",
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me"
+  },
+  "main": "abbrev.js",
+  "scripts": {
+    "test": "node test.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/isaacs/abbrev-js"
+  },
+  "license": {
+    "type": "MIT",
+    "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE"
+  },
+  "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n    var abbrev = require(\"abbrev\");\n    abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n    \n    // returns:\n    { fl: 'flop'\n    , flo: 'flop'\n    , flop: 'flop'\n    , fol: 'folding'\n    , fold: 'folding'\n    , foldi: 'folding'\n    , foldin: 'folding'\n    , folding: 'folding'\n    , foo: 'foo'\n    , fool: 'fool'\n    }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/abbrev-js/issues"
+  },
+  "homepage": "https://github.com/isaacs/abbrev-js",
+  "_id": "abbrev@1.0.5",
+  "dist": {
+    "shasum": "6ead16d813db5ae9bd26d8ad2a27d26486b4fc02"
+  },
+  "_from": "abbrev@1",
+  "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/test.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/test.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/node_modules/abbrev/test.js	(revision 533)
@@ -0,0 +1,47 @@
+var abbrev = require('./abbrev.js')
+var assert = require("assert")
+var util = require("util")
+
+console.log("TAP Version 13")
+var count = 0
+
+function test (list, expect) {
+  count++
+  var actual = abbrev(list)
+  assert.deepEqual(actual, expect,
+    "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+
+    "actual: "+util.inspect(actual))
+  actual = abbrev.apply(exports, list)
+  assert.deepEqual(abbrev.apply(exports, list), expect,
+    "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+
+    "actual: "+util.inspect(actual))
+  console.log('ok - ' + list.join(' '))
+}
+
+test([ "ruby", "ruby", "rules", "rules", "rules" ],
+{ rub: 'ruby'
+, ruby: 'ruby'
+, rul: 'rules'
+, rule: 'rules'
+, rules: 'rules'
+})
+test(["fool", "foom", "pool", "pope"],
+{ fool: 'fool'
+, foom: 'foom'
+, poo: 'pool'
+, pool: 'pool'
+, pop: 'pope'
+, pope: 'pope'
+})
+test(["a", "ab", "abc", "abcd", "abcde", "acde"],
+{ a: 'a'
+, ab: 'ab'
+, abc: 'abc'
+, abcd: 'abcd'
+, abcde: 'abcde'
+, ac: 'acde'
+, acd: 'acde'
+, acde: 'acde'
+})
+
+console.log("0..%d", count)
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/node_modules/nopt/package.json	(revision 533)
@@ -0,0 +1,40 @@
+{
+  "name": "nopt",
+  "version": "2.0.0",
+  "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.",
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me/"
+  },
+  "main": "lib/nopt.js",
+  "scripts": {
+    "test": "node lib/nopt.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/isaacs/nopt"
+  },
+  "bin": {
+    "nopt": "./bin/nopt.js"
+  },
+  "license": {
+    "type": "MIT",
+    "url": "https://github.com/isaacs/nopt/raw/master/LICENSE"
+  },
+  "dependencies": {
+    "abbrev": "1"
+  },
+  "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it.  The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser.  We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system.  You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n    // my-program.js\n    var nopt = require(\"nopt\")\n      , Stream = require(\"stream\").Stream\n      , path = require(\"path\")\n      , knownOpts = { \"foo\" : [String, null]\n                    , \"bar\" : [Stream, Number]\n                    , \"baz\" : path\n                    , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n                    , \"flag\" : Boolean\n                    , \"pick\" : Boolean\n                    , \"many\" : [String, Array]\n                    }\n      , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n                     , \"b7\" : [\"--bar\", \"7\"]\n                     , \"m\" : [\"--bloo\", \"medium\"]\n                     , \"p\" : [\"--pick\"]\n                     , \"f\" : [\"--flag\"]\n                     }\n                 // everything is optional.\n                 // knownOpts and shorthands default to {}\n                 // arg list defaults to process.argv\n                 // slice defaults to 2\n      , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n    console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp  # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array.  The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string.  No parsing is done.\n* path: A file system path.  Gets resolved against cwd if not absolute.\n* url: A url.  If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n  then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`.  If an option is a boolean,\n  then it does not need a value, and its presence will imply `true` as\n  the value.  To negate boolean flags, do `--no-whatever` or `--whatever\n  false`\n* NaN: Means that the option is strictly not allowed.  Any value will\n  fail.\n* Stream: An object matching the \"Stream\" class in node.  Valuable\n  for use when validating programmatically.  (npm uses this to let you\n  supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n  will be parsed as a list of options.  This means that multiple values\n  can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values.  For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list.  For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null.  When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`.  Each item in that\nhash is an object with a `type` member and a `validate` method.  The\n`type` member is an object that matches what goes in the type list.  The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`.  Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found.  You can change this behavior by assigning a method\nto `nopt.invalidHandler`.  This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining.  If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported.  If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts.  For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you.  So they're sliced off by\ndefault.  If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/nopt/issues"
+  },
+  "homepage": "https://github.com/isaacs/nopt",
+  "_id": "nopt@2.0.0",
+  "dist": {
+    "shasum": "f1cae880b8decd8e2f47918564a2270033dfb14b"
+  },
+  "_from": "nopt@~2.0.0",
+  "_resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/package.json	(revision 533)
@@ -0,0 +1,33 @@
+{
+  "author": {
+    "name": "mklabs"
+  },
+  "name": "noptify",
+  "description": "nopt wrapper with commander-like API",
+  "version": "0.0.3",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mklabs/noptify.git"
+  },
+  "dependencies": {
+    "nopt": "~2.0.0"
+  },
+  "devDependencies": {
+    "mocha": "~1.8.1"
+  },
+  "scripts": {
+    "test": "mocha --reporter spec"
+  },
+  "readme": "### noptify\n\nnoptify is a little wrapper around `nopt` module adding a more expressive,\ncommander-like, API and few helpers.\n\nExamples\n\n     var program = noptify(process.argv, { program: 'name' })\n       .version('0.0.1')\n       .option('port', '-p', 'Port to listen on (default: 35729)', Number)\n       .option('pid', 'Path to the generated PID file', String)\n\n     var opts = program.parse();\n\nReturns an instance of `Noptify`\n\n### Noptify\n\nNoptify provides the API to parse out option, shorthands and generate the\nproper generic help output.\n\n- args     - The Array of arguments to parse (default: `process.argv`);\n- options  - An hash of options with the following properties\n  - program - The program name to use in usage output\n\nEvery noptify instance is created with two options, `-h, --help` and `-v,\n--version`.\n\n### Noptify#parse\n\nParse the provided options and shorthands, pass them through `nopt` and\nreturn the result.\n\nWhen `opts.help` is set, the help output is displayed and `help`\nevent is emitted. The process exists with `0` status, the help output is\nautomatically displayed and the `help` event is emitted.\n\nExamples\n\n    var program = noptify(['foo', '--help'])\n      .on('help', function() {\n        console.log('Examples');\n        console.log('');\n        console.log('  foo bar --baz > foo.txt');\n      });\n\n    var opts = program.parse();\n    // ... Help output ...\n    // ... Custom help output ...\n    // ... Exit ...\n\n\n\n### Noptify#version\n\nDefine the program version.\n\n### Noptify#option\n\nDefine `name` option with optional shorthands, optional description and optional type.\n\n### Noptify#help\n\nSimply output to stdout the Usage and Help output.\n\n---\n\n*Mocha generated documentation*\n\n- [API](#api)\n- [Collectable](#collectable)\n- [Commandable](#commandable)\n  - [Parses remaining arguments and route to the appropriate command](#commandable-parses-remaining-arguments-and-route-to-the-appropriate-command)\n\n<a name=\"\"></a>\n\n<a name=\"api\"></a>\n## API\nreturns an instanceof Noptify.\n\n```js\nassert.ok(noptify() instanceof noptify.Noptify);\n```\n\nis typically used like so.\n\n```js\nvar program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'])\n  .option('debug', '-d', 'Enabled debug output', Boolean)\n  .option('dirname', 'The path to the output directory')\n  .option('port', '-p', 'The port you wish to listen on', Number)\n\n// opts => nopt result\nvar opts = program.parse();\n\nassert.deepEqual(opts, {\n  port: 3000,\n  debug: true,\n  dirname: './',\n  argv: {\n    remain: ['app.js', 'base.js'],\n    cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'],\n    original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']\n  }\n});\n```\n\nallows definitiion of shorthands separately.\n\n```js\nvar opts = noptify(['node', 'file.js', '-lc'])\n  .option('line-comment', 'Ouputs with debugging information', Boolean)\n  .shorthand('lc', '--line-comment')\n  .parse();\n\nassert.equal(opts['line-comment'], true);\n```\n\n<a name=\"collectable\"></a>\n## Collectable\nprovides the helper method to read from stdin.\n\n```js\nvar program = noptify();\nassert.ok(typeof program.stdin === 'function', 'stdin defined');\n```\n\nis invoked only when .parse() is called.\n\n```js\nvar program = noptify(['', '']);\nvar str = 'testing out stdin helper';\nprogram.stdin(function(err, res) {\n  assert.equal(res, str);\n  done();\n});\n\nprogram.parse();\n\nprocess.nextTick(function() {\n  process.stdin.emit('data', str);\n  process.stdin.emit('end');\n});\n```\n\n<a name=\"commandable\"></a>\n## Commandable\nprovides the .command() utility.\n\n```js\nassert.ok(typeof noptify().command === 'function');\n```\n\n<a name=\"commandable-parses-remaining-arguments-and-route-to-the-appropriate-command\"></a>\n## Parses remaining arguments and route to the appropriate command\ncan be a simple function.\n\n```js\nvar program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option');\n\nprogram.command('init', function(args, opts) {\n  // args ==> sliced args at command position\n  // opts ==> nopt parsed object\n  assert.deepEqual(args, ['--debug', 'foo']);\n  assert.equal(opts.debug, true);\n  assert.equal(opts.argv.remain[0], 'foo');\n  done();\n});\n\nprogram.parse();\n```\n\nor another program, an Noptify instance.\n\n```js\nvar args = ['', '', 'init', '--debug', 'myapp', 'foo'];\n\nvar init = noptify(args)\n  .option('debug', 'Debug output')\n  .command('myapp', done.bind(null, null));\n\nnoptify(args).command('init', init).parse();\n```\n\n",
+  "readmeFilename": "readme.md",
+  "bugs": {
+    "url": "https://github.com/mklabs/noptify/issues"
+  },
+  "homepage": "https://github.com/mklabs/noptify",
+  "_id": "noptify@0.0.3",
+  "dist": {
+    "shasum": "6aa6018734679e2f4a00baef6e9782066a42d599"
+  },
+  "_from": "noptify@~0.0.3",
+  "_resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/readme.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/readme.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/readme.md	(revision 533)
@@ -0,0 +1,184 @@
+### noptify
+
+noptify is a little wrapper around `nopt` module adding a more expressive,
+commander-like, API and few helpers.
+
+Examples
+
+     var program = noptify(process.argv, { program: 'name' })
+       .version('0.0.1')
+       .option('port', '-p', 'Port to listen on (default: 35729)', Number)
+       .option('pid', 'Path to the generated PID file', String)
+
+     var opts = program.parse();
+
+Returns an instance of `Noptify`
+
+### Noptify
+
+Noptify provides the API to parse out option, shorthands and generate the
+proper generic help output.
+
+- args     - The Array of arguments to parse (default: `process.argv`);
+- options  - An hash of options with the following properties
+  - program - The program name to use in usage output
+
+Every noptify instance is created with two options, `-h, --help` and `-v,
+--version`.
+
+### Noptify#parse
+
+Parse the provided options and shorthands, pass them through `nopt` and
+return the result.
+
+When `opts.help` is set, the help output is displayed and `help`
+event is emitted. The process exists with `0` status, the help output is
+automatically displayed and the `help` event is emitted.
+
+Examples
+
+    var program = noptify(['foo', '--help'])
+      .on('help', function() {
+        console.log('Examples');
+        console.log('');
+        console.log('  foo bar --baz > foo.txt');
+      });
+
+    var opts = program.parse();
+    // ... Help output ...
+    // ... Custom help output ...
+    // ... Exit ...
+
+
+
+### Noptify#version
+
+Define the program version.
+
+### Noptify#option
+
+Define `name` option with optional shorthands, optional description and optional type.
+
+### Noptify#help
+
+Simply output to stdout the Usage and Help output.
+
+---
+
+*Mocha generated documentation*
+
+- [API](#api)
+- [Collectable](#collectable)
+- [Commandable](#commandable)
+  - [Parses remaining arguments and route to the appropriate command](#commandable-parses-remaining-arguments-and-route-to-the-appropriate-command)
+
+<a name=""></a>
+
+<a name="api"></a>
+## API
+returns an instanceof Noptify.
+
+```js
+assert.ok(noptify() instanceof noptify.Noptify);
+```
+
+is typically used like so.
+
+```js
+var program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'])
+  .option('debug', '-d', 'Enabled debug output', Boolean)
+  .option('dirname', 'The path to the output directory')
+  .option('port', '-p', 'The port you wish to listen on', Number)
+
+// opts => nopt result
+var opts = program.parse();
+
+assert.deepEqual(opts, {
+  port: 3000,
+  debug: true,
+  dirname: './',
+  argv: {
+    remain: ['app.js', 'base.js'],
+    cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'],
+    original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']
+  }
+});
+```
+
+allows definitiion of shorthands separately.
+
+```js
+var opts = noptify(['node', 'file.js', '-lc'])
+  .option('line-comment', 'Ouputs with debugging information', Boolean)
+  .shorthand('lc', '--line-comment')
+  .parse();
+
+assert.equal(opts['line-comment'], true);
+```
+
+<a name="collectable"></a>
+## Collectable
+provides the helper method to read from stdin.
+
+```js
+var program = noptify();
+assert.ok(typeof program.stdin === 'function', 'stdin defined');
+```
+
+is invoked only when .parse() is called.
+
+```js
+var program = noptify(['', '']);
+var str = 'testing out stdin helper';
+program.stdin(function(err, res) {
+  assert.equal(res, str);
+  done();
+});
+
+program.parse();
+
+process.nextTick(function() {
+  process.stdin.emit('data', str);
+  process.stdin.emit('end');
+});
+```
+
+<a name="commandable"></a>
+## Commandable
+provides the .command() utility.
+
+```js
+assert.ok(typeof noptify().command === 'function');
+```
+
+<a name="commandable-parses-remaining-arguments-and-route-to-the-appropriate-command"></a>
+## Parses remaining arguments and route to the appropriate command
+can be a simple function.
+
+```js
+var program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option');
+
+program.command('init', function(args, opts) {
+  // args ==> sliced args at command position
+  // opts ==> nopt parsed object
+  assert.deepEqual(args, ['--debug', 'foo']);
+  assert.equal(opts.debug, true);
+  assert.equal(opts.argv.remain[0], 'foo');
+  done();
+});
+
+program.parse();
+```
+
+or another program, an Noptify instance.
+
+```js
+var args = ['', '', 'init', '--debug', 'myapp', 'foo'];
+
+var init = noptify(args)
+  .option('debug', 'Debug output')
+  .command('myapp', done.bind(null, null));
+
+noptify(args).command('init', init).parse();
+```
+
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/api.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/api.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/api.js	(revision 533)
@@ -0,0 +1,53 @@
+var noptify = require('..');
+var assert  = require('assert');
+
+describe('API', function() {
+
+  it('returns an instanceof Noptify', function() {
+    assert.ok(noptify() instanceof noptify.Noptify);
+  });
+
+
+  it('is typically used like so', function() {
+    var program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'])
+      .option('debug', '-d', 'Enabled debug output', Boolean)
+      .option('dirname', 'The path to the output directory')
+      .option('port', '-p', 'The port you wish to listen on', Number)
+
+    // opts => nopt result
+    var opts = program.parse();
+
+    assert.deepEqual(opts, {
+      port: 3000,
+      debug: true,
+      dirname: './',
+      argv: {
+        remain: ['app.js', 'base.js'],
+        cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'],
+        original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']
+      }
+    });
+  });
+
+  it('allows definitiion of shorthands separately', function() {
+    var opts = noptify(['node', 'file.js', '-lc'])
+      .option('line-comment', 'Ouputs with debugging information', Boolean)
+      .shorthand('lc', '--line-comment')
+      .parse();
+
+    assert.equal(opts['line-comment'], true);
+  });
+
+  // hmm, keep this one for the very last, or do another way, process exit
+  // prevent other tests from running
+  it.skip('outputs help and exit the process with --help', function() {
+    var program = noptify(['', '', '--help'])
+    assert.throws(function() {
+      throw new Error('parse() must be called for this to happen');
+    });
+
+    program.parse();
+    throw new Error('I\'m sad, I\'ll never throw :(');
+  });
+
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/collectable.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/collectable.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/collectable.js	(revision 533)
@@ -0,0 +1,40 @@
+var noptify = require('..');
+var assert = require('assert');
+
+
+describe('Collectable', function() {
+
+  it('provides the helper method to read from stdin', function() {
+    var program = noptify();
+    assert.ok(typeof program.stdin === 'function', 'stdin defined');
+  });
+
+  it('is invoked only when .parse() is called', function(done) {
+    var program = noptify(['', '']);
+    var str = 'testing out stdin helper';
+    program.stdin(function(err, res) {
+      assert.equal(res, str);
+      done();
+    });
+
+    program.parse();
+
+    process.nextTick(function() {
+      process.stdin.emit('data', str);
+      process.stdin.emit('end');
+    });
+  });
+
+
+  it('.files()', function(done) {
+    var program = noptify(['', '', 'test/fixtures/a.js', 'test/fixtures/b.js']);
+    program.parse();
+
+    program.files(function(err, data) {
+      assert.equal(data, 'a\nb\n');
+      done();
+    });
+
+  });
+
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/commandable.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/commandable.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/commandable.js	(revision 533)
@@ -0,0 +1,40 @@
+var noptify = require('..');
+var assert  = require('assert');
+
+describe('Commandable', function() {
+
+  it('provides the .command() utility', function() {
+    assert.ok(typeof noptify().command === 'function');
+  });
+
+
+  describe('Parses remaining arguments and route to the appropriate command', function() {
+
+    it('can be a simple function', function(done) {
+      var program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option');
+
+      program.command('init', function(args, opts) {
+        // args ==> sliced args at command position
+        // opts ==> nopt parsed object
+        assert.deepEqual(args, ['--debug', 'foo']);
+        assert.equal(opts.debug, true);
+        assert.equal(opts.argv.remain[0], 'foo');
+        done();
+      });
+
+      program.parse();
+    });
+
+    it('or another program, an Noptify instance', function(done) {
+      var args = ['', '', 'init', '--debug', 'myapp', 'foo'];
+
+      var init = noptify(args)
+        .option('debug', 'Debug output')
+        .command('myapp', done.bind(null, null));
+
+      noptify(args).command('init', init).parse();
+    });
+  });
+
+
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/fixtures/a.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/fixtures/a.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/fixtures/a.js	(revision 533)
@@ -0,0 +1,1 @@
+a
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/fixtures/b.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/fixtures/b.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/test/fixtures/b.js	(revision 533)
@@ -0,0 +1,1 @@
+b
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/util/extend.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/util/extend.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/util/extend.js	(revision 533)
@@ -0,0 +1,15 @@
+
+
+// Simple extend utility method
+
+module.exports = function extend(obj) {
+  var args = Array.prototype.slice.call(arguments, 1);
+
+  args.forEach(function(o) {
+    Object.keys(o).forEach(function(prop) {
+      obj[prop] = o[prop];
+    });
+  });
+
+  return obj;
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/util/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/util/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/noptify/util/index.js	(revision 533)
@@ -0,0 +1,6 @@
+
+// Common interface to utility methods, exposing the standard `util` core module
+var util = module.exports = require('util');
+
+// and augmenting it
+util.extend = require('./extend');
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.gitmodules
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.gitmodules	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.gitmodules	(revision 533)
@@ -0,0 +1,6 @@
+[submodule "support/expresso"]
+	path = support/expresso
+	url = git://github.com/visionmedia/expresso.git
+[submodule "support/should"]
+	path = support/should
+	url = git://github.com/visionmedia/should.js.git
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.npmignore
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.npmignore	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.npmignore	(revision 533)
@@ -0,0 +1,1 @@
+node_modules
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.travis.yml
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.travis.yml	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/.travis.yml	(revision 533)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.4
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/History.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/History.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/History.md	(revision 533)
@@ -0,0 +1,109 @@
+
+0.5.6 / 2013-04-09 
+==================
+
+  * fix empty key productions in parser
+
+0.5.5 / 2013-03-20 
+==================
+
+  * output key= for null or undefined values. Closes #52
+
+0.5.4 / 2013-03-15 
+==================
+
+  * fix ignoring of null / undefined. Closes #44
+
+0.5.3 2012-12-09 
+==================
+
+  * add info to component.json
+  * remove regular client-side ./querystring.js, fix component.json support
+
+0.5.2 / 2012-11-14 
+==================
+
+  * fix uri encoding of non-plain object string values
+
+0.5.1 / 2012-09-18 
+==================
+
+  * fix encoded `=`. Closes #43
+
+0.5.0 / 2012-05-04 
+==================
+
+  * Added component support
+
+0.4.2 / 2012-02-08 
+==================
+
+  * Fixed: ensure objects are created when appropriate not arrays [aheckmann]
+
+0.4.1 / 2012-01-26 
+==================
+
+  * Fixed stringify()ing numbers. Closes #23
+
+0.4.0 / 2011-11-21 
+==================
+
+  * Allow parsing of an existing object (for `bodyParser()`) [jackyz]
+  * Replaced expresso with mocha
+
+0.3.2 / 2011-11-08 
+==================
+
+  * Fixed global variable leak
+
+0.3.1 / 2011-08-17 
+==================
+
+  * Added `try/catch` around malformed uri components
+  * Add test coverage for Array native method bleed-though
+
+0.3.0 / 2011-07-19 
+==================
+
+  * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart]
+
+0.2.0 / 2011-06-29 
+==================
+
+  * Added `qs.stringify()` [Cory Forsyth]
+
+0.1.0 / 2011-04-13 
+==================
+
+  * Added jQuery-ish array support
+
+0.0.7 / 2011-03-13 
+==================
+
+  * Fixed; handle empty string and `== null` in `qs.parse()` [dmit]
+    allows for convenient `qs.parse(url.parse(str).query)`
+
+0.0.6 / 2011-02-14 
+==================
+
+  * Fixed; support for implicit arrays
+
+0.0.4 / 2011-02-09 
+==================
+
+  * Fixed `+` as a space
+
+0.0.3 / 2011-02-08 
+==================
+
+  * Fixed case when right-hand value contains "]"
+
+0.0.2 / 2011-02-07 
+==================
+
+  * Fixed "=" presence in key
+
+0.0.1 / 2011-02-07 
+==================
+
+  * Initial release
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/Makefile
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/Makefile	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/Makefile	(revision 533)
@@ -0,0 +1,6 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--ui bdd
+
+.PHONY: test
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/Readme.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/Readme.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/Readme.md	(revision 533)
@@ -0,0 +1,58 @@
+# node-querystring
+
+  query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
+
+## Installation
+
+    $ npm install qs
+
+## Examples
+
+```js
+var qs = require('qs');
+
+qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
+// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
+
+qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
+// => user[name]=Tobi&user[email]=tobi%40learnboost.com
+```
+
+## Testing
+
+Install dev dependencies:
+
+    $ npm install -d
+
+and execute:
+
+    $ make test
+
+browser:
+
+    $ open test/browser/index.html
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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.
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/benchmark.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/benchmark.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/benchmark.js	(revision 533)
@@ -0,0 +1,17 @@
+
+var qs = require('./');
+
+var times = 100000
+  , start = new Date
+  , n = times;
+
+console.log('times: %d', times);
+
+while (n--) qs.parse('foo=bar');
+console.log('simple: %dms', new Date - start);
+
+var start = new Date
+  , n = times;
+
+while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log('nested: %dms', new Date - start);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/component.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/component.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/component.json	(revision 533)
@@ -0,0 +1,9 @@
+{
+  "name": "querystring",
+  "repo": "visionmedia/node-querystring",
+  "description": "query-string parser / stringifier with nesting support",
+  "version": "0.5.6",
+  "keywords": ["querystring", "query", "parser"],
+  "scripts": ["index.js"],
+  "license": "MIT"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/examples.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/examples.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/examples.js	(revision 533)
@@ -0,0 +1,51 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('./');
+
+var obj = qs.parse('foo');
+console.log(obj)
+
+var obj = qs.parse('foo=bar=baz');
+console.log(obj)
+
+var obj = qs.parse('users[]');
+console.log(obj)
+
+var obj = qs.parse('name=tj&email=tj@vision-media.ca');
+console.log(obj)
+
+var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
+console.log(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log(obj)
+
+var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
+console.log(obj)
+
+var obj = qs.parse('a=a&a=b&a=c');
+console.log(obj)
+
+var obj = qs.parse('user[tj]=tj&user[tj]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler');
+console.log(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[1]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[foo]=TJ');
+console.log(obj)
+
+var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }});
+console.log(str);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/index.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/index.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/index.js	(revision 533)
@@ -0,0 +1,268 @@
+
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+  if (parent[key].length == 0) return parent[key] = {};
+  var t = {};
+  for (var i in parent[key]) t[i] = parent[key][i];
+  parent[key] = t;
+  return t;
+}
+
+function parse(parts, parent, key, val) {
+  var part = parts.shift();
+  // end
+  if (!part) {
+    if (Array.isArray(parent[key])) {
+      parent[key].push(val);
+    } else if ('object' == typeof parent[key]) {
+      parent[key] = val;
+    } else if ('undefined' == typeof parent[key]) {
+      parent[key] = val;
+    } else {
+      parent[key] = [parent[key], val];
+    }
+    // array
+  } else {
+    var obj = parent[key] = parent[key] || [];
+    if (']' == part) {
+      if (Array.isArray(obj)) {
+        if ('' != val) obj.push(val);
+      } else if ('object' == typeof obj) {
+        obj[Object.keys(obj).length] = val;
+      } else {
+        obj = parent[key] = [parent[key], val];
+      }
+      // prop
+    } else if (~part.indexOf(']')) {
+      part = part.substr(0, part.length - 1);
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+      // key
+    } else {
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+    }
+  }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+  if (~key.indexOf(']')) {
+    var parts = key.split('[')
+      , len = parts.length
+      , last = len - 1;
+    parse(parts, parent, 'base', val);
+    // optimize
+  } else {
+    if (!isint.test(key) && Array.isArray(parent.base)) {
+      var t = {};
+      for (var k in parent.base) t[k] = parent.base[k];
+      parent.base = t;
+    }
+    set(parent.base, key, val);
+  }
+
+  return parent;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+  var ret = { base: {} };
+  Object.keys(obj).forEach(function(name){
+    merge(ret, name, obj[name]);
+  });
+  return ret.base;
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+  return String(str)
+    .split('&')
+    .reduce(function(ret, pair){
+      var eql = pair.indexOf('=')
+        , brace = lastBraceInKey(pair)
+        , key = pair.substr(0, brace || eql)
+        , val = pair.substr(brace || eql, pair.length)
+        , val = val.substr(val.indexOf('=') + 1, val.length);
+
+      // ?foo
+      if ('' == key) key = pair, val = '';
+      if ('' == key) return ret;
+
+      return merge(ret, decode(key), decode(val));
+    }, { base: {} }).base;
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+  if (null == str || '' == str) return {};
+  return 'object' == typeof str
+    ? parseObject(str)
+    : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+  if (Array.isArray(obj)) {
+    return stringifyArray(obj, prefix);
+  } else if ('[object Object]' == toString.call(obj)) {
+    return stringifyObject(obj, prefix);
+  } else if ('string' == typeof obj) {
+    return stringifyString(obj, prefix);
+  } else {
+    return prefix + '=' + encodeURIComponent(String(obj));
+  }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+  if (!prefix) throw new TypeError('stringify expects an object');
+  return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+  var ret = [];
+  if (!prefix) throw new TypeError('stringify expects an object');
+  for (var i = 0; i < arr.length; i++) {
+    ret.push(stringify(arr[i], prefix + '[' + i + ']'));
+  }
+  return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+  var ret = []
+    , keys = Object.keys(obj)
+    , key;
+
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    key = keys[i];
+    if ('' == key) continue;
+    if (null == obj[key]) {
+      ret.push(encodeURIComponent(key) + '=');
+    } else {
+      ret.push(stringify(obj[key], prefix
+        ? prefix + '[' + encodeURIComponent(key) + ']'
+        : encodeURIComponent(key)));
+    }
+  }
+
+  return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+  var v = obj[key];
+  if (undefined === v) {
+    obj[key] = val;
+  } else if (Array.isArray(v)) {
+    v.push(val);
+  } else {
+    obj[key] = [v, val];
+  }
+}
+
+/**
+ * Locate last brace in `str` within the key.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function lastBraceInKey(str) {
+  var len = str.length
+    , brace
+    , c;
+  for (var i = 0; i < len; ++i) {
+    c = str[i];
+    if (']' == c) brace = false;
+    if ('[' == c) brace = true;
+    if ('=' == c && !brace) return i;
+  }
+}
+
+/**
+ * Decode `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function decode(str) {
+  try {
+    return decodeURIComponent(str.replace(/\+/g, ' '));
+  } catch (err) {
+    return str;
+  }
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/package.json	(revision 533)
@@ -0,0 +1,44 @@
+{
+  "name": "qs",
+  "description": "querystring parser",
+  "version": "0.5.6",
+  "keywords": [
+    "query string",
+    "parser",
+    "component"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/node-querystring.git"
+  },
+  "devDependencies": {
+    "mocha": "*",
+    "expect.js": "*"
+  },
+  "component": {
+    "scripts": {
+      "querystring": "querystring.js"
+    }
+  },
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "main": "index",
+  "engines": {
+    "node": "*"
+  },
+  "readme": "# node-querystring\n\n  query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n    $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n    $ npm install -d\n\nand execute:\n\n    $ make test\n\nbrowser:\n\n    $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/node-querystring/issues"
+  },
+  "homepage": "https://github.com/visionmedia/node-querystring",
+  "_id": "qs@0.5.6",
+  "dist": {
+    "shasum": "2152c1f2476417de489a399e1e39eef9a6267cd1"
+  },
+  "_from": "qs@~0.5.2",
+  "_resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/expect.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/expect.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/expect.js	(revision 533)
@@ -0,0 +1,1202 @@
+
+(function (global, module) {
+
+  if ('undefined' == typeof module) {
+    var module = { exports: {} }
+      , exports = module.exports
+  }
+
+  /**
+   * Exports.
+   */
+
+  module.exports = expect;
+  expect.Assertion = Assertion;
+
+  /**
+   * Exports version.
+   */
+
+  expect.version = '0.1.2';
+
+  /**
+   * Possible assertion flags.
+   */
+
+  var flags = {
+      not: ['to', 'be', 'have', 'include', 'only']
+    , to: ['be', 'have', 'include', 'only', 'not']
+    , only: ['have']
+    , have: ['own']
+    , be: ['an']
+  };
+
+  function expect (obj) {
+    return new Assertion(obj);
+  }
+
+  /**
+   * Constructor
+   *
+   * @api private
+   */
+
+  function Assertion (obj, flag, parent) {
+    this.obj = obj;
+    this.flags = {};
+
+    if (undefined != parent) {
+      this.flags[flag] = true;
+
+      for (var i in parent.flags) {
+        if (parent.flags.hasOwnProperty(i)) {
+          this.flags[i] = true;
+        }
+      }
+    }
+
+    var $flags = flag ? flags[flag] : keys(flags)
+      , self = this
+
+    if ($flags) {
+      for (var i = 0, l = $flags.length; i < l; i++) {
+        // avoid recursion
+        if (this.flags[$flags[i]]) continue;
+
+        var name = $flags[i]
+          , assertion = new Assertion(this.obj, name, this)
+  
+        if ('function' == typeof Assertion.prototype[name]) {
+          // clone the function, make sure we dont touch the prot reference
+          var old = this[name];
+          this[name] = function () {
+            return old.apply(self, arguments);
+          }
+
+          for (var fn in Assertion.prototype) {
+            if (Assertion.prototype.hasOwnProperty(fn) && fn != name) {
+              this[name][fn] = bind(assertion[fn], assertion);
+            }
+          }
+        } else {
+          this[name] = assertion;
+        }
+      }
+    }
+  };
+
+  /**
+   * Performs an assertion
+   *
+   * @api private
+   */
+
+  Assertion.prototype.assert = function (truth, msg, error) {
+    var msg = this.flags.not ? error : msg
+      , ok = this.flags.not ? !truth : truth;
+
+    if (!ok) {
+      throw new Error(msg);
+    }
+
+    this.and = new Assertion(this.obj);
+  };
+
+  /**
+   * Check if the value is truthy
+   *
+   * @api public
+   */
+
+  Assertion.prototype.ok = function () {
+    this.assert(
+        !!this.obj
+      , 'expected ' + i(this.obj) + ' to be truthy'
+      , 'expected ' + i(this.obj) + ' to be falsy');
+  };
+
+  /**
+   * Assert that the function throws.
+   *
+   * @param {Function|RegExp} callback, or regexp to match error string against
+   * @api public
+   */
+
+  Assertion.prototype.throwError =
+  Assertion.prototype.throwException = function (fn) {
+    expect(this.obj).to.be.a('function');
+
+    var thrown = false
+      , not = this.flags.not
+
+    try {
+      this.obj();
+    } catch (e) {
+      if ('function' == typeof fn) {
+        fn(e);
+      } else if ('object' == typeof fn) {
+        var subject = 'string' == typeof e ? e : e.message;
+        if (not) {
+          expect(subject).to.not.match(fn);
+        } else {
+          expect(subject).to.match(fn);
+        }
+      }
+      thrown = true;
+    }
+
+    if ('object' == typeof fn && not) {
+      // in the presence of a matcher, ensure the `not` only applies to
+      // the matching.
+      this.flags.not = false; 
+    }
+
+    var name = this.obj.name || 'fn';
+    this.assert(
+        thrown
+      , 'expected ' + name + ' to throw an exception'
+      , 'expected ' + name + ' not to throw an exception');
+  };
+
+  /**
+   * Checks if the array is empty.
+   *
+   * @api public
+   */
+
+  Assertion.prototype.empty = function () {
+    var expectation;
+
+    if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) {
+      if ('number' == typeof this.obj.length) {
+        expectation = !this.obj.length;
+      } else {
+        expectation = !keys(this.obj).length;
+      }
+    } else {
+      if ('string' != typeof this.obj) {
+        expect(this.obj).to.be.an('object');
+      }
+
+      expect(this.obj).to.have.property('length');
+      expectation = !this.obj.length;
+    }
+
+    this.assert(
+        expectation
+      , 'expected ' + i(this.obj) + ' to be empty'
+      , 'expected ' + i(this.obj) + ' to not be empty');
+    return this;
+  };
+
+  /**
+   * Checks if the obj exactly equals another.
+   *
+   * @api public
+   */
+
+  Assertion.prototype.be =
+  Assertion.prototype.equal = function (obj) {
+    this.assert(
+        obj === this.obj
+      , 'expected ' + i(this.obj) + ' to equal ' + i(obj)
+      , 'expected ' + i(this.obj) + ' to not equal ' + i(obj));
+    return this;
+  };
+
+  /**
+   * Checks if the obj sortof equals another.
+   *
+   * @api public
+   */
+
+  Assertion.prototype.eql = function (obj) {
+    this.assert(
+        expect.eql(obj, this.obj)
+      , 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj)
+      , 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj));
+    return this;
+  };
+
+  /**
+   * Assert within start to finish (inclusive). 
+   *
+   * @param {Number} start
+   * @param {Number} finish
+   * @api public
+   */
+
+  Assertion.prototype.within = function (start, finish) {
+    var range = start + '..' + finish;
+    this.assert(
+        this.obj >= start && this.obj <= finish
+      , 'expected ' + i(this.obj) + ' to be within ' + range
+      , 'expected ' + i(this.obj) + ' to not be within ' + range);
+    return this;
+  };
+
+  /**
+   * Assert typeof / instance of
+   *
+   * @api public
+   */
+
+  Assertion.prototype.a =
+  Assertion.prototype.an = function (type) {
+    if ('string' == typeof type) {
+      // proper english in error msg
+      var n = /^[aeiou]/.test(type) ? 'n' : '';
+
+      // typeof with support for 'array'
+      this.assert(
+          'array' == type ? isArray(this.obj) :
+            'object' == type
+              ? 'object' == typeof this.obj && null !== this.obj
+              : type == typeof this.obj
+        , 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type
+        , 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type);
+    } else {
+      // instanceof
+      var name = type.name || 'supplied constructor';
+      this.assert(
+          this.obj instanceof type
+        , 'expected ' + i(this.obj) + ' to be an instance of ' + name
+        , 'expected ' + i(this.obj) + ' not to be an instance of ' + name);
+    }
+
+    return this;
+  };
+
+  /**
+   * Assert numeric value above _n_.
+   *
+   * @param {Number} n
+   * @api public
+   */
+
+  Assertion.prototype.greaterThan =
+  Assertion.prototype.above = function (n) {
+    this.assert(
+        this.obj > n
+      , 'expected ' + i(this.obj) + ' to be above ' + n
+      , 'expected ' + i(this.obj) + ' to be below ' + n);
+    return this;
+  };
+
+  /**
+   * Assert numeric value below _n_.
+   *
+   * @param {Number} n
+   * @api public
+   */
+
+  Assertion.prototype.lessThan =
+  Assertion.prototype.below = function (n) {
+    this.assert(
+        this.obj < n
+      , 'expected ' + i(this.obj) + ' to be below ' + n
+      , 'expected ' + i(this.obj) + ' to be above ' + n);
+    return this;
+  };
+  
+  /**
+   * Assert string value matches _regexp_.
+   *
+   * @param {RegExp} regexp
+   * @api public
+   */
+
+  Assertion.prototype.match = function (regexp) {
+    this.assert(
+        regexp.exec(this.obj)
+      , 'expected ' + i(this.obj) + ' to match ' + regexp
+      , 'expected ' + i(this.obj) + ' not to match ' + regexp);
+    return this;
+  };
+
+  /**
+   * Assert property "length" exists and has value of _n_.
+   *
+   * @param {Number} n
+   * @api public
+   */
+
+  Assertion.prototype.length = function (n) {
+    expect(this.obj).to.have.property('length');
+    var len = this.obj.length;
+    this.assert(
+        n == len
+      , 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len
+      , 'expected ' + i(this.obj) + ' to not have a length of ' + len);
+    return this;
+  };
+
+  /**
+   * Assert property _name_ exists, with optional _val_.
+   *
+   * @param {String} name
+   * @param {Mixed} val
+   * @api public
+   */
+
+  Assertion.prototype.property = function (name, val) {
+    if (this.flags.own) {
+      this.assert(
+          Object.prototype.hasOwnProperty.call(this.obj, name)
+        , 'expected ' + i(this.obj) + ' to have own property ' + i(name)
+        , 'expected ' + i(this.obj) + ' to not have own property ' + i(name));
+      return this;
+    }
+
+    if (this.flags.not && undefined !== val) {
+      if (undefined === this.obj[name]) {
+        throw new Error(i(this.obj) + ' has no property ' + i(name));
+      }
+    } else {
+      var hasProp;
+      try {
+        hasProp = name in this.obj
+      } catch (e) {
+        hasProp = undefined !== this.obj[name]
+      }
+      
+      this.assert(
+          hasProp
+        , 'expected ' + i(this.obj) + ' to have a property ' + i(name)
+        , 'expected ' + i(this.obj) + ' to not have a property ' + i(name));
+    }
+    
+    if (undefined !== val) {
+      this.assert(
+          val === this.obj[name]
+        , 'expected ' + i(this.obj) + ' to have a property ' + i(name)
+          + ' of ' + i(val) + ', but got ' + i(this.obj[name])
+        , 'expected ' + i(this.obj) + ' to not have a property ' + i(name)
+          + ' of ' + i(val));
+    }
+
+    this.obj = this.obj[name];
+    return this;
+  };
+
+  /**
+   * Assert that the array contains _obj_ or string contains _obj_.
+   *
+   * @param {Mixed} obj|string
+   * @api public
+   */
+
+  Assertion.prototype.string =
+  Assertion.prototype.contain = function (obj) {
+    if ('string' == typeof this.obj) {
+      this.assert(
+          ~this.obj.indexOf(obj)
+        , 'expected ' + i(this.obj) + ' to contain ' + i(obj)
+        , 'expected ' + i(this.obj) + ' to not contain ' + i(obj));
+    } else {
+      this.assert(
+          ~indexOf(this.obj, obj)
+        , 'expected ' + i(this.obj) + ' to contain ' + i(obj)
+        , 'expected ' + i(this.obj) + ' to not contain ' + i(obj));
+    }
+    return this;
+  };
+
+  /**
+   * Assert exact keys or inclusion of keys by using
+   * the `.own` modifier.
+   *
+   * @param {Array|String ...} keys
+   * @api public
+   */
+
+  Assertion.prototype.key =
+  Assertion.prototype.keys = function ($keys) {
+    var str
+      , ok = true;
+
+    $keys = isArray($keys)
+      ? $keys
+      : Array.prototype.slice.call(arguments);
+
+    if (!$keys.length) throw new Error('keys required');
+
+    var actual = keys(this.obj)
+      , len = $keys.length;
+
+    // Inclusion
+    ok = every($keys, function (key) {
+      return ~indexOf(actual, key);
+    });
+
+    // Strict
+    if (!this.flags.not && this.flags.only) {
+      ok = ok && $keys.length == actual.length;
+    }
+
+    // Key string
+    if (len > 1) {
+      $keys = map($keys, function (key) {
+        return i(key);
+      });
+      var last = $keys.pop();
+      str = $keys.join(', ') + ', and ' + last;
+    } else {
+      str = i($keys[0]);
+    }
+
+    // Form
+    str = (len > 1 ? 'keys ' : 'key ') + str;
+
+    // Have / include
+    str = (!this.flags.only ? 'include ' : 'only have ') + str;
+
+    // Assertion
+    this.assert(
+        ok
+      , 'expected ' + i(this.obj) + ' to ' + str
+      , 'expected ' + i(this.obj) + ' to not ' + str);
+
+    return this;
+  };
+
+  /**
+   * Function bind implementation.
+   */
+
+  function bind (fn, scope) {
+    return function () {
+      return fn.apply(scope, arguments);
+    }
+  }
+
+  /**
+   * Array every compatibility
+   *
+   * @see bit.ly/5Fq1N2
+   * @api public
+   */
+
+  function every (arr, fn, thisObj) {
+    var scope = thisObj || global;
+    for (var i = 0, j = arr.length; i < j; ++i) {
+      if (!fn.call(scope, arr[i], i, arr)) {
+        return false;
+      }
+    }
+    return true;
+  };
+
+  /**
+   * Array indexOf compatibility.
+   *
+   * @see bit.ly/a5Dxa2
+   * @api public
+   */
+
+  function indexOf (arr, o, i) {
+    if (Array.prototype.indexOf) {
+      return Array.prototype.indexOf.call(arr, o, i);
+    }
+
+    if (arr.length === undefined) {
+      return -1;
+    }
+
+    for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0
+        ; i < j && arr[i] !== o; i++);
+
+    return j <= i ? -1 : i;
+  };
+
+  /**
+   * Inspects an object.
+   *
+   * @see taken from node.js `util` module (copyright Joyent, MIT license)
+   * @api private
+   */
+
+  function i (obj, showHidden, depth) {
+    var seen = [];
+
+    function stylize (str) {
+      return str;
+    };
+
+    function format (value, recurseTimes) {
+      // Provide a hook for user-specified inspect functions.
+      // Check that value is an object with an inspect function on it
+      if (value && typeof value.inspect === 'function' &&
+          // Filter out the util module, it's inspect function is special
+          value !== exports &&
+          // Also filter out any prototype objects using the circular check.
+          !(value.constructor && value.constructor.prototype === value)) {
+        return value.inspect(recurseTimes);
+      }
+
+      // Primitive types cannot have properties
+      switch (typeof value) {
+        case 'undefined':
+          return stylize('undefined', 'undefined');
+
+        case 'string':
+          var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '')
+                                                   .replace(/'/g, "\\'")
+                                                   .replace(/\\"/g, '"') + '\'';
+          return stylize(simple, 'string');
+
+        case 'number':
+          return stylize('' + value, 'number');
+
+        case 'boolean':
+          return stylize('' + value, 'boolean');
+      }
+      // For some reason typeof null is "object", so special case here.
+      if (value === null) {
+        return stylize('null', 'null');
+      }
+
+      // Look up the keys of the object.
+      var visible_keys = keys(value);
+      var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys;
+
+      // Functions without properties can be shortcutted.
+      if (typeof value === 'function' && $keys.length === 0) {
+        if (isRegExp(value)) {
+          return stylize('' + value, 'regexp');
+        } else {
+          var name = value.name ? ': ' + value.name : '';
+          return stylize('[Function' + name + ']', 'special');
+        }
+      }
+
+      // Dates without properties can be shortcutted
+      if (isDate(value) && $keys.length === 0) {
+        return stylize(value.toUTCString(), 'date');
+      }
+
+      var base, type, braces;
+      // Determine the object type
+      if (isArray(value)) {
+        type = 'Array';
+        braces = ['[', ']'];
+      } else {
+        type = 'Object';
+        braces = ['{', '}'];
+      }
+
+      // Make functions say that they are functions
+      if (typeof value === 'function') {
+        var n = value.name ? ': ' + value.name : '';
+        base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
+      } else {
+        base = '';
+      }
+
+      // Make dates with properties first say the date
+      if (isDate(value)) {
+        base = ' ' + value.toUTCString();
+      }
+
+      if ($keys.length === 0) {
+        return braces[0] + base + braces[1];
+      }
+
+      if (recurseTimes < 0) {
+        if (isRegExp(value)) {
+          return stylize('' + value, 'regexp');
+        } else {
+          return stylize('[Object]', 'special');
+        }
+      }
+
+      seen.push(value);
+
+      var output = map($keys, function (key) {
+        var name, str;
+        if (value.__lookupGetter__) {
+          if (value.__lookupGetter__(key)) {
+            if (value.__lookupSetter__(key)) {
+              str = stylize('[Getter/Setter]', 'special');
+            } else {
+              str = stylize('[Getter]', 'special');
+            }
+          } else {
+            if (value.__lookupSetter__(key)) {
+              str = stylize('[Setter]', 'special');
+            }
+          }
+        }
+        if (indexOf(visible_keys, key) < 0) {
+          name = '[' + key + ']';
+        }
+        if (!str) {
+          if (indexOf(seen, value[key]) < 0) {
+            if (recurseTimes === null) {
+              str = format(value[key]);
+            } else {
+              str = format(value[key], recurseTimes - 1);
+            }
+            if (str.indexOf('\n') > -1) {
+              if (isArray(value)) {
+                str = map(str.split('\n'), function (line) {
+                  return '  ' + line;
+                }).join('\n').substr(2);
+              } else {
+                str = '\n' + map(str.split('\n'), function (line) {
+                  return '   ' + line;
+                }).join('\n');
+              }
+            }
+          } else {
+            str = stylize('[Circular]', 'special');
+          }
+        }
+        if (typeof name === 'undefined') {
+          if (type === 'Array' && key.match(/^\d+$/)) {
+            return str;
+          }
+          name = json.stringify('' + key);
+          if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+            name = name.substr(1, name.length - 2);
+            name = stylize(name, 'name');
+          } else {
+            name = name.replace(/'/g, "\\'")
+                       .replace(/\\"/g, '"')
+                       .replace(/(^"|"$)/g, "'");
+            name = stylize(name, 'string');
+          }
+        }
+
+        return name + ': ' + str;
+      });
+
+      seen.pop();
+
+      var numLinesEst = 0;
+      var length = reduce(output, function (prev, cur) {
+        numLinesEst++;
+        if (indexOf(cur, '\n') >= 0) numLinesEst++;
+        return prev + cur.length + 1;
+      }, 0);
+
+      if (length > 50) {
+        output = braces[0] +
+                 (base === '' ? '' : base + '\n ') +
+                 ' ' +
+                 output.join(',\n  ') +
+                 ' ' +
+                 braces[1];
+
+      } else {
+        output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+      }
+
+      return output;
+    }
+    return format(obj, (typeof depth === 'undefined' ? 2 : depth));
+  };
+
+  function isArray (ar) {
+    return Object.prototype.toString.call(ar) == '[object Array]';
+  };
+
+  function isRegExp(re) {
+    var s = '' + re;
+    return re instanceof RegExp || // easy case
+           // duck-type for context-switching evalcx case
+           typeof(re) === 'function' &&
+           re.constructor.name === 'RegExp' &&
+           re.compile &&
+           re.test &&
+           re.exec &&
+           s.match(/^\/.*\/[gim]{0,3}$/);
+  };
+
+  function isDate(d) {
+    if (d instanceof Date) return true;
+    return false;
+  };
+
+  function keys (obj) {
+    if (Object.keys) {
+      return Object.keys(obj);
+    }
+
+    var keys = [];
+
+    for (var i in obj) {
+      if (Object.prototype.hasOwnProperty.call(obj, i)) {
+        keys.push(i);
+      }
+    }
+
+    return keys;
+  }
+
+  function map (arr, mapper, that) {
+    if (Array.prototype.map) {
+      return Array.prototype.map.call(arr, mapper, that);
+    }
+
+    var other= new Array(arr.length);
+
+    for (var i= 0, n = arr.length; i<n; i++)
+      if (i in arr)
+        other[i] = mapper.call(that, arr[i], i, arr);
+
+    return other;
+  };
+
+  function reduce (arr, fun) {
+    if (Array.prototype.reduce) {
+      return Array.prototype.reduce.apply(
+          arr
+        , Array.prototype.slice.call(arguments, 1)
+      );
+    }
+
+    var len = +this.length;
+
+    if (typeof fun !== "function")
+      throw new TypeError();
+
+    // no value to return if no initial value and an empty array
+    if (len === 0 && arguments.length === 1)
+      throw new TypeError();
+
+    var i = 0;
+    if (arguments.length >= 2) {
+      var rv = arguments[1];
+    } else {
+      do {
+        if (i in this) {
+          rv = this[i++];
+          break;
+        }
+
+        // if array contains no values, no initial value to return
+        if (++i >= len)
+          throw new TypeError();
+      } while (true);
+    }
+
+    for (; i < len; i++) {
+      if (i in this)
+        rv = fun.call(null, rv, this[i], i, this);
+    }
+
+    return rv;
+  };
+
+  /**
+   * Asserts deep equality
+   *
+   * @see taken from node.js `assert` module (copyright Joyent, MIT license)
+   * @api private
+   */
+
+  expect.eql = function eql (actual, expected) {
+    // 7.1. All identical values are equivalent, as determined by ===.
+    if (actual === expected) { 
+      return true;
+    } else if ('undefined' != typeof Buffer 
+        && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
+      if (actual.length != expected.length) return false;
+
+      for (var i = 0; i < actual.length; i++) {
+        if (actual[i] !== expected[i]) return false;
+      }
+
+      return true;
+
+    // 7.2. If the expected value is a Date object, the actual value is
+    // equivalent if it is also a Date object that refers to the same time.
+    } else if (actual instanceof Date && expected instanceof Date) {
+      return actual.getTime() === expected.getTime();
+
+    // 7.3. Other pairs that do not both pass typeof value == "object",
+    // equivalence is determined by ==.
+    } else if (typeof actual != 'object' && typeof expected != 'object') {
+      return actual == expected;
+
+    // 7.4. For all other Object pairs, including Array objects, equivalence is
+    // determined by having the same number of owned properties (as verified
+    // with Object.prototype.hasOwnProperty.call), the same set of keys
+    // (although not necessarily the same order), equivalent values for every
+    // corresponding key, and an identical "prototype" property. Note: this
+    // accounts for both named and indexed properties on Arrays.
+    } else {
+      return objEquiv(actual, expected);
+    }
+  }
+
+  function isUndefinedOrNull (value) {
+    return value === null || value === undefined;
+  }
+
+  function isArguments (object) {
+    return Object.prototype.toString.call(object) == '[object Arguments]';
+  }
+
+  function objEquiv (a, b) {
+    if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
+      return false;
+    // an identical "prototype" property.
+    if (a.prototype !== b.prototype) return false;
+    //~~~I've managed to break Object.keys through screwy arguments passing.
+    //   Converting to array solves the problem.
+    if (isArguments(a)) {
+      if (!isArguments(b)) {
+        return false;
+      }
+      a = pSlice.call(a);
+      b = pSlice.call(b);
+      return expect.eql(a, b);
+    }
+    try{
+      var ka = keys(a),
+        kb = keys(b),
+        key, i;
+    } catch (e) {//happens when one is a string literal and the other isn't
+      return false;
+    }
+    // having the same number of owned properties (keys incorporates hasOwnProperty)
+    if (ka.length != kb.length)
+      return false;
+    //the same set of keys (although not necessarily the same order),
+    ka.sort();
+    kb.sort();
+    //~~~cheap key test
+    for (i = ka.length - 1; i >= 0; i--) {
+      if (ka[i] != kb[i])
+        return false;
+    }
+    //equivalent values for every corresponding key, and
+    //~~~possibly expensive deep test
+    for (i = ka.length - 1; i >= 0; i--) {
+      key = ka[i];
+      if (!expect.eql(a[key], b[key]))
+         return false;
+    }
+    return true;
+  }
+
+  var json = (function () {
+    "use strict";
+
+    if ('object' == typeof JSON && JSON.parse && JSON.stringify) {
+      return {
+          parse: nativeJSON.parse
+        , stringify: nativeJSON.stringify
+      }
+    }
+
+    var JSON = {};
+
+    function f(n) {
+        // Format integers to have at least two digits.
+        return n < 10 ? '0' + n : n;
+    }
+
+    function date(d, key) {
+      return isFinite(d.valueOf()) ?
+          d.getUTCFullYear()     + '-' +
+          f(d.getUTCMonth() + 1) + '-' +
+          f(d.getUTCDate())      + 'T' +
+          f(d.getUTCHours())     + ':' +
+          f(d.getUTCMinutes())   + ':' +
+          f(d.getUTCSeconds())   + 'Z' : null;
+    };
+
+    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        gap,
+        indent,
+        meta = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        rep;
+
+
+    function quote(string) {
+
+  // If the string contains no control characters, no quote characters, and no
+  // backslash characters, then we can safely slap some quotes around it.
+  // Otherwise we must also replace the offending characters with safe escape
+  // sequences.
+
+        escapable.lastIndex = 0;
+        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
+            var c = meta[a];
+            return typeof c === 'string' ? c :
+                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+        }) + '"' : '"' + string + '"';
+    }
+
+
+    function str(key, holder) {
+
+  // Produce a string from holder[key].
+
+        var i,          // The loop counter.
+            k,          // The member key.
+            v,          // The member value.
+            length,
+            mind = gap,
+            partial,
+            value = holder[key];
+
+  // If the value has a toJSON method, call it to obtain a replacement value.
+
+        if (value instanceof Date) {
+            value = date(key);
+        }
+
+  // If we were called with a replacer function, then call the replacer to
+  // obtain a replacement value.
+
+        if (typeof rep === 'function') {
+            value = rep.call(holder, key, value);
+        }
+
+  // What happens next depends on the value's type.
+
+        switch (typeof value) {
+        case 'string':
+            return quote(value);
+
+        case 'number':
+
+  // JSON numbers must be finite. Encode non-finite numbers as null.
+
+            return isFinite(value) ? String(value) : 'null';
+
+        case 'boolean':
+        case 'null':
+
+  // If the value is a boolean or null, convert it to a string. Note:
+  // typeof null does not produce 'null'. The case is included here in
+  // the remote chance that this gets fixed someday.
+
+            return String(value);
+
+  // If the type is 'object', we might be dealing with an object or an array or
+  // null.
+
+        case 'object':
+
+  // Due to a specification blunder in ECMAScript, typeof null is 'object',
+  // so watch out for that case.
+
+            if (!value) {
+                return 'null';
+            }
+
+  // Make an array to hold the partial results of stringifying this object value.
+
+            gap += indent;
+            partial = [];
+
+  // Is the value an array?
+
+            if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+  // The value is an array. Stringify every element. Use null as a placeholder
+  // for non-JSON values.
+
+                length = value.length;
+                for (i = 0; i < length; i += 1) {
+                    partial[i] = str(i, value) || 'null';
+                }
+
+  // Join all of the elements together, separated with commas, and wrap them in
+  // brackets.
+
+                v = partial.length === 0 ? '[]' : gap ?
+                    '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
+                    '[' + partial.join(',') + ']';
+                gap = mind;
+                return v;
+            }
+
+  // If the replacer is an array, use it to select the members to be stringified.
+
+            if (rep && typeof rep === 'object') {
+                length = rep.length;
+                for (i = 0; i < length; i += 1) {
+                    if (typeof rep[i] === 'string') {
+                        k = rep[i];
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            } else {
+
+  // Otherwise, iterate through all of the keys in the object.
+
+                for (k in value) {
+                    if (Object.prototype.hasOwnProperty.call(value, k)) {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            }
+
+  // Join all of the member texts together, separated with commas,
+  // and wrap them in braces.
+
+            v = partial.length === 0 ? '{}' : gap ?
+                '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
+                '{' + partial.join(',') + '}';
+            gap = mind;
+            return v;
+        }
+    }
+
+  // If the JSON object does not yet have a stringify method, give it one.
+
+    JSON.stringify = function (value, replacer, space) {
+
+  // The stringify method takes a value and an optional replacer, and an optional
+  // space parameter, and returns a JSON text. The replacer can be a function
+  // that can replace values, or an array of strings that will select the keys.
+  // A default replacer method can be provided. Use of the space parameter can
+  // produce text that is more easily readable.
+
+        var i;
+        gap = '';
+        indent = '';
+
+  // If the space parameter is a number, make an indent string containing that
+  // many spaces.
+
+        if (typeof space === 'number') {
+            for (i = 0; i < space; i += 1) {
+                indent += ' ';
+            }
+
+  // If the space parameter is a string, it will be used as the indent string.
+
+        } else if (typeof space === 'string') {
+            indent = space;
+        }
+
+  // If there is a replacer, it must be a function or an array.
+  // Otherwise, throw an error.
+
+        rep = replacer;
+        if (replacer && typeof replacer !== 'function' &&
+                (typeof replacer !== 'object' ||
+                typeof replacer.length !== 'number')) {
+            throw new Error('JSON.stringify');
+        }
+
+  // Make a fake root object containing our value under the key of ''.
+  // Return the result of stringifying the value.
+
+        return str('', {'': value});
+    };
+
+  // If the JSON object does not yet have a parse method, give it one.
+
+    JSON.parse = function (text, reviver) {
+    // The parse method takes a text and an optional reviver function, and returns
+    // a JavaScript value if the text is a valid JSON text.
+
+        var j;
+
+        function walk(holder, key) {
+
+    // The walk method is used to recursively walk the resulting structure so
+    // that modifications can be made.
+
+            var k, v, value = holder[key];
+            if (value && typeof value === 'object') {
+                for (k in value) {
+                    if (Object.prototype.hasOwnProperty.call(value, k)) {
+                        v = walk(value, k);
+                        if (v !== undefined) {
+                            value[k] = v;
+                        } else {
+                            delete value[k];
+                        }
+                    }
+                }
+            }
+            return reviver.call(holder, key, value);
+        }
+
+
+    // Parsing happens in four stages. In the first stage, we replace certain
+    // Unicode characters with escape sequences. JavaScript handles many characters
+    // incorrectly, either silently deleting them, or treating them as line endings.
+
+        text = String(text);
+        cx.lastIndex = 0;
+        if (cx.test(text)) {
+            text = text.replace(cx, function (a) {
+                return '\\u' +
+                    ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+            });
+        }
+
+    // In the second stage, we run the text against regular expressions that look
+    // for non-JSON patterns. We are especially concerned with '()' and 'new'
+    // because they can cause invocation, and '=' because it can cause mutation.
+    // But just to be safe, we want to reject all unexpected forms.
+
+    // We split the second stage into 4 regexp operations in order to work around
+    // crippling inefficiencies in IE's and Safari's regexp engines. First we
+    // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+    // replace all simple value tokens with ']' characters. Third, we delete all
+    // open brackets that follow a colon or comma or that begin the text. Finally,
+    // we look to see that the remaining characters are only whitespace or ']' or
+    // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+        if (/^[\],:{}\s]*$/
+                .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
+                    .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+                    .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+    // In the third stage we use the eval function to compile the text into a
+    // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+    // in JavaScript: it can begin a block or an object literal. We wrap the text
+    // in parens to eliminate the ambiguity.
+
+            j = eval('(' + text + ')');
+
+    // In the optional fourth stage, we recursively walk the new structure, passing
+    // each name/value pair to a reviver function for possible transformation.
+
+            return typeof reviver === 'function' ?
+                walk({'': j}, '') : j;
+        }
+
+    // If the text is not JSON parseable, then a SyntaxError is thrown.
+
+        throw new SyntaxError('JSON.parse');
+    };
+
+    return JSON;
+  })();
+
+  if ('undefined' != typeof window) {
+    window.expect = module.exports;
+  }
+
+})(
+    this
+  , 'undefined' != typeof module ? module : {}
+  , 'undefined' != typeof exports ? exports : {}
+);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/index.html
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/index.html	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/index.html	(revision 533)
@@ -0,0 +1,18 @@
+<html>
+  <head>
+    <title>Mocha</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <link rel="stylesheet" href="mocha.css" />
+    <script src="jquery.js" type="text/javascript"></script>
+    <script src="expect.js"></script>
+    <script src="mocha.js"></script>
+    <script>mocha.setup('bdd')</script>
+    <script src="qs.js"></script>
+    <script src="../parse.js"></script>
+    <script src="../stringify.js"></script>
+    <script>onload = mocha.run;</script>
+  </head>
+  <body>
+    <div id="mocha"></div>
+  </body>
+</html>
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/jquery.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/jquery.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/jquery.js	(revision 533)
@@ -0,0 +1,8981 @@
+/*!
+ * jQuery JavaScript Library v1.6.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Jun 30 14:16:56 2011 -0400
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+	navigator = window.navigator,
+	location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context, rootjQuery );
+	},
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	// A central reference to the root jQuery(document)
+	rootjQuery,
+
+	// A simple way to check for HTML strings or ID strings
+	// (both of which we optimize for)
+	quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+	// Check if a string has a non-whitespace character in it
+	rnotwhite = /\S/,
+
+	// Used for trimming whitespace
+	trimLeft = /^\s+/,
+	trimRight = /\s+$/,
+
+	// Check for digits
+	rdigit = /\d/,
+
+	// Match a standalone tag
+	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+	// JSON RegExp
+	rvalidchars = /^[\],:{}\s]*$/,
+	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+	// Useragent RegExp
+	rwebkit = /(webkit)[ \/]([\w.]+)/,
+	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+	rmsie = /(msie) ([\w.]+)/,
+	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+	// Matches dashed string for camelizing
+	rdashAlpha = /-([a-z])/ig,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	},
+
+	// Keep a UserAgent string for use with jQuery.browser
+	userAgent = navigator.userAgent,
+
+	// For matching the engine and version of the browser
+	browserMatch,
+
+	// The deferred used on DOM ready
+	readyList,
+
+	// The ready event handler
+	DOMContentLoaded,
+
+	// Save a reference to some core methods
+	toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty,
+	push = Array.prototype.push,
+	slice = Array.prototype.slice,
+	trim = String.prototype.trim,
+	indexOf = Array.prototype.indexOf,
+
+	// [[Class]] -> type pairs
+	class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+	constructor: jQuery,
+	init: function( selector, context, rootjQuery ) {
+		var match, elem, ret, doc;
+
+		// Handle $(""), $(null), or $(undefined)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// The body element only exists once, optimize finding it
+		if ( selector === "body" && !context && document.body ) {
+			this.context = document;
+			this[0] = document.body;
+			this.selector = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = quickExpr.exec( selector );
+			}
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+					doc = (context ? context.ownerDocument || context : document);
+
+					// If a single string is passed in and it's a single tag
+					// just do a createElement and skip the rest
+					ret = rsingleTag.exec( selector );
+
+					if ( ret ) {
+						if ( jQuery.isPlainObject( context ) ) {
+							selector = [ document.createElement( ret[1] ) ];
+							jQuery.fn.attr.call( selector, context, true );
+
+						} else {
+							selector = [ doc.createElement( ret[1] ) ];
+						}
+
+					} else {
+						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+						selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
+					}
+
+					return jQuery.merge( this, selector );
+
+				// HANDLE: $("#id")
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return (context || rootjQuery).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return rootjQuery.ready( selector );
+		}
+
+		if (selector.selector !== undefined) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.6.2",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	toArray: function() {
+		return slice.call( this, 0 );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == null ?
+
+			// Return a 'clean' array
+			this.toArray() :
+
+			// Return just the object
+			( num < 0 ? this[ this.length + num ] : this[ num ] );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = this.constructor();
+
+		if ( jQuery.isArray( elems ) ) {
+			push.apply( ret, elems );
+
+		} else {
+			jQuery.merge( ret, elems );
+		}
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" ) {
+			ret.selector = this.selector + (this.selector ? " " : "") + selector;
+		} else if ( name ) {
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+		}
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	ready: function( fn ) {
+		// Attach the listeners
+		jQuery.bindReady();
+
+		// Add the callback
+		readyList.done( fn );
+
+		return this;
+	},
+
+	eq: function( i ) {
+		return i === -1 ?
+			this.slice( i ) :
+			this.slice( i, +i + 1 );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ),
+			"slice", slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: [].sort,
+	splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( length === i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		if ( window.$ === jQuery ) {
+			window.$ = _$;
+		}
+
+		if ( deep && window.jQuery === jQuery ) {
+			window.jQuery = _jQuery;
+		}
+
+		return jQuery;
+	},
+
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+		// Either a released hold or an DOMready/load event and not yet ready
+		if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+			if ( !document.body ) {
+				return setTimeout( jQuery.ready, 1 );
+			}
+
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If a normal DOM Ready event fired, decrement, and wait if need be
+			if ( wait !== true && --jQuery.readyWait > 0 ) {
+				return;
+			}
+
+			// If there are functions bound, to execute
+			readyList.resolveWith( document, [ jQuery ] );
+
+			// Trigger any bound ready events
+			if ( jQuery.fn.trigger ) {
+				jQuery( document ).trigger( "ready" ).unbind( "ready" );
+			}
+		}
+	},
+
+	bindReady: function() {
+		if ( readyList ) {
+			return;
+		}
+
+		readyList = jQuery._Deferred();
+
+		// Catch cases where $(document).ready() is called after the
+		// browser event has already occurred.
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			return setTimeout( jQuery.ready, 1 );
+		}
+
+		// Mozilla, Opera and webkit nightlies currently support this event
+		if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", jQuery.ready, false );
+
+		// If IE event model is used
+		} else if ( document.attachEvent ) {
+			// ensure firing before onload,
+			// maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", jQuery.ready );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var toplevel = false;
+
+			try {
+				toplevel = window.frameElement == null;
+			} catch(e) {}
+
+			if ( document.documentElement.doScroll && toplevel ) {
+				doScrollCheck();
+			}
+		}
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	// A crude way of determining if an object is a window
+	isWindow: function( obj ) {
+		return obj && typeof obj === "object" && "setInterval" in obj;
+	},
+
+	isNaN: function( obj ) {
+		return obj == null || !rdigit.test( obj ) || isNaN( obj );
+	},
+
+	type: function( obj ) {
+		return obj == null ?
+			String( obj ) :
+			class2type[ toString.call(obj) ] || "object";
+	},
+
+	isPlainObject: function( obj ) {
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		// Not own constructor property must be Object
+		if ( obj.constructor &&
+			!hasOwn.call(obj, "constructor") &&
+			!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+			return false;
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+
+		var key;
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		for ( var name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	error: function( msg ) {
+		throw msg;
+	},
+
+	parseJSON: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+
+		// Make sure leading/trailing whitespace is removed (IE can't handle it)
+		data = jQuery.trim( data );
+
+		// Attempt to parse using the native JSON parser first
+		if ( window.JSON && window.JSON.parse ) {
+			return window.JSON.parse( data );
+		}
+
+		// Make sure the incoming data is actual JSON
+		// Logic borrowed from http://json.org/json2.js
+		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+			.replace( rvalidtokens, "]" )
+			.replace( rvalidbraces, "")) ) {
+
+			return (new Function( "return " + data ))();
+
+		}
+		jQuery.error( "Invalid JSON: " + data );
+	},
+
+	// Cross-browser xml parsing
+	// (xml & tmp used internally)
+	parseXML: function( data , xml , tmp ) {
+
+		if ( window.DOMParser ) { // Standard
+			tmp = new DOMParser();
+			xml = tmp.parseFromString( data , "text/xml" );
+		} else { // IE
+			xml = new ActiveXObject( "Microsoft.XMLDOM" );
+			xml.async = "false";
+			xml.loadXML( data );
+		}
+
+		tmp = xml.documentElement;
+
+		if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
+			jQuery.error( "Invalid XML: " + data );
+		}
+
+		return xml;
+	},
+
+	noop: function() {},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && rnotwhite.test( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Converts a dashed string to camelCased string;
+	// Used by both the css and data modules
+	camelCase: function( string ) {
+		return string.replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0,
+			length = object.length,
+			isObj = length === undefined || jQuery.isFunction( object );
+
+		if ( args ) {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.apply( object[ name ], args ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.apply( object[ i++ ], args ) === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return object;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: trim ?
+		function( text ) {
+			return text == null ?
+				"" :
+				trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( array, results ) {
+		var ret = results || [];
+
+		if ( array != null ) {
+			// The window, strings (and functions) also have 'length'
+			// The extra typeof function check is to prevent crashes
+			// in Safari 2 (See: #3039)
+			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+			var type = jQuery.type( array );
+
+			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+				push.call( ret, array );
+			} else {
+				jQuery.merge( ret, array );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+
+		if ( indexOf ) {
+			return indexOf.call( array, elem );
+		}
+
+		for ( var i = 0, length = array.length; i < length; i++ ) {
+			if ( array[ i ] === elem ) {
+				return i;
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var i = first.length,
+			j = 0;
+
+		if ( typeof second.length === "number" ) {
+			for ( var l = second.length; j < l; j++ ) {
+				first[ i++ ] = second[ j ];
+			}
+
+		} else {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [], retVal;
+		inv = !!inv;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			retVal = !!callback( elems[ i ], i );
+			if ( inv !== retVal ) {
+				ret.push( elems[ i ] );
+			}
+		}
+
+		return ret;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value, key, ret = [],
+			i = 0,
+			length = elems.length,
+			// jquery objects are treated as arrays
+			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+		// Go through the array, translating each of the items to their
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( key in elems ) {
+				value = callback( elems[ key ], key, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return ret.concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		if ( typeof context === "string" ) {
+			var tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		var args = slice.call( arguments, 2 ),
+			proxy = function() {
+				return fn.apply( context, args.concat( slice.call( arguments ) ) );
+			};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	// Mutifunctional method to get and set values to a collection
+	// The value/s can optionally be executed if it's a function
+	access: function( elems, key, value, exec, fn, pass ) {
+		var length = elems.length;
+
+		// Setting many attributes
+		if ( typeof key === "object" ) {
+			for ( var k in key ) {
+				jQuery.access( elems, k, key[k], exec, fn, value );
+			}
+			return elems;
+		}
+
+		// Setting one attribute
+		if ( value !== undefined ) {
+			// Optionally, function values get executed if exec is true
+			exec = !pass && exec && jQuery.isFunction(value);
+
+			for ( var i = 0; i < length; i++ ) {
+				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+			}
+
+			return elems;
+		}
+
+		// Getting an attribute
+		return length ? fn( elems[0], key ) : undefined;
+	},
+
+	now: function() {
+		return (new Date()).getTime();
+	},
+
+	// Use of jQuery.browser is frowned upon.
+	// More details: http://docs.jquery.com/Utilities/jQuery.browser
+	uaMatch: function( ua ) {
+		ua = ua.toLowerCase();
+
+		var match = rwebkit.exec( ua ) ||
+			ropera.exec( ua ) ||
+			rmsie.exec( ua ) ||
+			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+			[];
+
+		return { browser: match[1] || "", version: match[2] || "0" };
+	},
+
+	sub: function() {
+		function jQuerySub( selector, context ) {
+			return new jQuerySub.fn.init( selector, context );
+		}
+		jQuery.extend( true, jQuerySub, this );
+		jQuerySub.superclass = this;
+		jQuerySub.fn = jQuerySub.prototype = this();
+		jQuerySub.fn.constructor = jQuerySub;
+		jQuerySub.sub = this.sub;
+		jQuerySub.fn.init = function init( selector, context ) {
+			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+				context = jQuerySub( context );
+			}
+
+			return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+		};
+		jQuerySub.fn.init.prototype = jQuerySub.fn;
+		var rootjQuerySub = jQuerySub(document);
+		return jQuerySub;
+	},
+
+	browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+	jQuery.browser[ browserMatch.browser ] = true;
+	jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+	jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+	trimLeft = /^[\s\xA0]+/;
+	trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+	DOMContentLoaded = function() {
+		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+		jQuery.ready();
+	};
+
+} else if ( document.attachEvent ) {
+	DOMContentLoaded = function() {
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( document.readyState === "complete" ) {
+			document.detachEvent( "onreadystatechange", DOMContentLoaded );
+			jQuery.ready();
+		}
+	};
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+	if ( jQuery.isReady ) {
+		return;
+	}
+
+	try {
+		// If IE is used, use the trick by Diego Perini
+		// http://javascript.nwbox.com/IEContentLoaded/
+		document.documentElement.doScroll("left");
+	} catch(e) {
+		setTimeout( doScrollCheck, 1 );
+		return;
+	}
+
+	// and execute any waiting functions
+	jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+var // Promise methods
+	promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
+	// Static reference to slice
+	sliceDeferred = [].slice;
+
+jQuery.extend({
+	// Create a simple deferred (one callbacks list)
+	_Deferred: function() {
+		var // callbacks list
+			callbacks = [],
+			// stored [ context , args ]
+			fired,
+			// to avoid firing when already doing so
+			firing,
+			// flag to know if the deferred has been cancelled
+			cancelled,
+			// the deferred itself
+			deferred  = {
+
+				// done( f1, f2, ...)
+				done: function() {
+					if ( !cancelled ) {
+						var args = arguments,
+							i,
+							length,
+							elem,
+							type,
+							_fired;
+						if ( fired ) {
+							_fired = fired;
+							fired = 0;
+						}
+						for ( i = 0, length = args.length; i < length; i++ ) {
+							elem = args[ i ];
+							type = jQuery.type( elem );
+							if ( type === "array" ) {
+								deferred.done.apply( deferred, elem );
+							} else if ( type === "function" ) {
+								callbacks.push( elem );
+							}
+						}
+						if ( _fired ) {
+							deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
+						}
+					}
+					return this;
+				},
+
+				// resolve with given context and args
+				resolveWith: function( context, args ) {
+					if ( !cancelled && !fired && !firing ) {
+						// make sure args are available (#8421)
+						args = args || [];
+						firing = 1;
+						try {
+							while( callbacks[ 0 ] ) {
+								callbacks.shift().apply( context, args );
+							}
+						}
+						finally {
+							fired = [ context, args ];
+							firing = 0;
+						}
+					}
+					return this;
+				},
+
+				// resolve with this as context and given arguments
+				resolve: function() {
+					deferred.resolveWith( this, arguments );
+					return this;
+				},
+
+				// Has this deferred been resolved?
+				isResolved: function() {
+					return !!( firing || fired );
+				},
+
+				// Cancel
+				cancel: function() {
+					cancelled = 1;
+					callbacks = [];
+					return this;
+				}
+			};
+
+		return deferred;
+	},
+
+	// Full fledged deferred (two callbacks list)
+	Deferred: function( func ) {
+		var deferred = jQuery._Deferred(),
+			failDeferred = jQuery._Deferred(),
+			promise;
+		// Add errorDeferred methods, then and promise
+		jQuery.extend( deferred, {
+			then: function( doneCallbacks, failCallbacks ) {
+				deferred.done( doneCallbacks ).fail( failCallbacks );
+				return this;
+			},
+			always: function() {
+				return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
+			},
+			fail: failDeferred.done,
+			rejectWith: failDeferred.resolveWith,
+			reject: failDeferred.resolve,
+			isRejected: failDeferred.isResolved,
+			pipe: function( fnDone, fnFail ) {
+				return jQuery.Deferred(function( newDefer ) {
+					jQuery.each( {
+						done: [ fnDone, "resolve" ],
+						fail: [ fnFail, "reject" ]
+					}, function( handler, data ) {
+						var fn = data[ 0 ],
+							action = data[ 1 ],
+							returned;
+						if ( jQuery.isFunction( fn ) ) {
+							deferred[ handler ](function() {
+								returned = fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise().then( newDefer.resolve, newDefer.reject );
+								} else {
+									newDefer[ action ]( returned );
+								}
+							});
+						} else {
+							deferred[ handler ]( newDefer[ action ] );
+						}
+					});
+				}).promise();
+			},
+			// Get a promise for this deferred
+			// If obj is provided, the promise aspect is added to the object
+			promise: function( obj ) {
+				if ( obj == null ) {
+					if ( promise ) {
+						return promise;
+					}
+					promise = obj = {};
+				}
+				var i = promiseMethods.length;
+				while( i-- ) {
+					obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
+				}
+				return obj;
+			}
+		});
+		// Make sure only one callback list will be used
+		deferred.done( failDeferred.cancel ).fail( deferred.cancel );
+		// Unexpose cancel
+		delete deferred.cancel;
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( firstParam ) {
+		var args = arguments,
+			i = 0,
+			length = args.length,
+			count = length,
+			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+				firstParam :
+				jQuery.Deferred();
+		function resolveFunc( i ) {
+			return function( value ) {
+				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+				if ( !( --count ) ) {
+					// Strange bug in FF4:
+					// Values changed onto the arguments object sometimes end up as undefined values
+					// outside the $.when method. Cloning the object into a fresh array solves the issue
+					deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
+				}
+			};
+		}
+		if ( length > 1 ) {
+			for( ; i < length; i++ ) {
+				if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
+					args[ i ].promise().then( resolveFunc(i), deferred.reject );
+				} else {
+					--count;
+				}
+			}
+			if ( !count ) {
+				deferred.resolveWith( deferred, args );
+			}
+		} else if ( deferred !== firstParam ) {
+			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+		}
+		return deferred.promise();
+	}
+});
+
+
+
+jQuery.support = (function() {
+
+	var div = document.createElement( "div" ),
+		documentElement = document.documentElement,
+		all,
+		a,
+		select,
+		opt,
+		input,
+		marginDiv,
+		support,
+		fragment,
+		body,
+		testElementParent,
+		testElement,
+		testElementStyle,
+		tds,
+		events,
+		eventName,
+		i,
+		isSupported;
+
+	// Preliminary tests
+	div.setAttribute("className", "t");
+	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+	all = div.getElementsByTagName( "*" );
+	a = div.getElementsByTagName( "a" )[ 0 ];
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return {};
+	}
+
+	// First batch of supports tests
+	select = document.createElement( "select" );
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName( "input" )[ 0 ];
+
+	support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName( "tbody" ).length,
+
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName( "link" ).length,
+
+		// Get the style information from getAttribute
+		// (IE uses .cssText instead)
+		style: /top/.test( a.getAttribute("style") ),
+
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
+
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		// Use a regex to work around a WebKit issue. See #5145
+		opacity: /^0.55$/.test( a.style.opacity ),
+
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Make sure that if no value is specified for a checkbox
+		// that it defaults to "on".
+		// (WebKit defaults to "" instead)
+		checkOn: ( input.value === "on" ),
+
+		// Make sure that a selected-by-default option has a working selected property.
+		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+		optSelected: opt.selected,
+
+		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+		getSetAttribute: div.className !== "t",
+
+		// Will be defined later
+		submitBubbles: true,
+		changeBubbles: true,
+		focusinBubbles: false,
+		deleteExpando: true,
+		noCloneEvent: true,
+		inlineBlockNeedsLayout: false,
+		shrinkWrapBlocks: false,
+		reliableMarginRight: true
+	};
+
+	// Make sure checked status is properly cloned
+	input.checked = true;
+	support.noCloneChecked = input.cloneNode( true ).checked;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Test to see if it's possible to delete an expando from an element
+	// Fails in Internet Explorer
+	try {
+		delete div.test;
+	} catch( e ) {
+		support.deleteExpando = false;
+	}
+
+	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+		div.attachEvent( "onclick", function() {
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			support.noCloneEvent = false;
+		});
+		div.cloneNode( true ).fireEvent( "onclick" );
+	}
+
+	// Check if a radio maintains it's value
+	// after being appended to the DOM
+	input = document.createElement("input");
+	input.value = "t";
+	input.setAttribute("type", "radio");
+	support.radioValue = input.value === "t";
+
+	input.setAttribute("checked", "checked");
+	div.appendChild( input );
+	fragment = document.createDocumentFragment();
+	fragment.appendChild( div.firstChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	div.innerHTML = "";
+
+	// Figure out if the W3C box model works as expected
+	div.style.width = div.style.paddingLeft = "1px";
+
+	body = document.getElementsByTagName( "body" )[ 0 ];
+	// We use our own, invisible, body unless the body is already present
+	// in which case we use a div (#9239)
+	testElement = document.createElement( body ? "div" : "body" );
+	testElementStyle = {
+		visibility: "hidden",
+		width: 0,
+		height: 0,
+		border: 0,
+		margin: 0
+	};
+	if ( body ) {
+		jQuery.extend( testElementStyle, {
+			position: "absolute",
+			left: -1000,
+			top: -1000
+		});
+	}
+	for ( i in testElementStyle ) {
+		testElement.style[ i ] = testElementStyle[ i ];
+	}
+	testElement.appendChild( div );
+	testElementParent = body || documentElement;
+	testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	support.appendChecked = input.checked;
+
+	support.boxModel = div.offsetWidth === 2;
+
+	if ( "zoom" in div.style ) {
+		// Check if natively block-level elements act like inline-block
+		// elements when setting their display to 'inline' and giving
+		// them layout
+		// (IE < 8 does this)
+		div.style.display = "inline";
+		div.style.zoom = 1;
+		support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
+
+		// Check if elements with layout shrink-wrap their children
+		// (IE 6 does this)
+		div.style.display = "";
+		div.innerHTML = "<div style='width:4px;'></div>";
+		support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
+	}
+
+	div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
+	tds = div.getElementsByTagName( "td" );
+
+	// Check if table cells still have offsetWidth/Height when they are set
+	// to display:none and there are still other visible table cells in a
+	// table row; if so, offsetWidth/Height are not reliable for use when
+	// determining if an element has been hidden directly using
+	// display:none (it is still safe to use offsets if a parent element is
+	// hidden; don safety goggles and see bug #4512 for more information).
+	// (only IE 8 fails this test)
+	isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+	tds[ 0 ].style.display = "";
+	tds[ 1 ].style.display = "none";
+
+	// Check if empty table cells still have offsetWidth/Height
+	// (IE < 8 fail this test)
+	support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+	div.innerHTML = "";
+
+	// Check if div with explicit width and no margin-right incorrectly
+	// gets computed margin-right based on width of container. For more
+	// info see bug #3333
+	// Fails in WebKit before Feb 2011 nightlies
+	// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+	if ( document.defaultView && document.defaultView.getComputedStyle ) {
+		marginDiv = document.createElement( "div" );
+		marginDiv.style.width = "0";
+		marginDiv.style.marginRight = "0";
+		div.appendChild( marginDiv );
+		support.reliableMarginRight =
+			( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+	}
+
+	// Remove the body element we added
+	testElement.innerHTML = "";
+	testElementParent.removeChild( testElement );
+
+	// Technique from Juriy Zaytsev
+	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+	// We only care about the case where non-standard event systems
+	// are used, namely in IE. Short-circuiting here helps us to
+	// avoid an eval call (in setAttribute) which can cause CSP
+	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+	if ( div.attachEvent ) {
+		for( i in {
+			submit: 1,
+			change: 1,
+			focusin: 1
+		} ) {
+			eventName = "on" + i;
+			isSupported = ( eventName in div );
+			if ( !isSupported ) {
+				div.setAttribute( eventName, "return;" );
+				isSupported = ( typeof div[ eventName ] === "function" );
+			}
+			support[ i + "Bubbles" ] = isSupported;
+		}
+	}
+
+	// Null connected elements to avoid leaks in IE
+	testElement = fragment = select = opt = body = marginDiv = div = input = null;
+
+	return support;
+})();
+
+// Keep track of boxModel
+jQuery.boxModel = jQuery.support.boxModel;
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+	rmultiDash = /([a-z])([A-Z])/g;
+
+jQuery.extend({
+	cache: {},
+
+	// Please use with caution
+	uuid: 0,
+
+	// Unique for each copy of jQuery on the page
+	// Non-digits removed to match rinlinejQuery
+	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+	// The following elements throw uncatchable exceptions if you
+	// attempt to add expando properties to them.
+	noData: {
+		"embed": true,
+		// Ban all objects except for Flash (which handle expandos)
+		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+		"applet": true
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
+
+			// We have to handle DOM nodes and JS objects differently because IE6-7
+			// can't GC object references properly across the DOM-JS boundary
+			isNode = elem.nodeType,
+
+			// Only DOM nodes need the global jQuery cache; JS object data is
+			// attached directly to the object so GC can occur automatically
+			cache = isNode ? jQuery.cache : elem,
+
+			// Only defining an ID for JS objects if its cache already exists allows
+			// the code to shortcut on the same path as a DOM node with no cache
+			id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
+
+		// Avoid doing any more work than we need to when trying to get data on an
+		// object that has no data at all
+		if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
+			return;
+		}
+
+		if ( !id ) {
+			// Only DOM nodes need a new unique ID for each element since their data
+			// ends up in the global cache
+			if ( isNode ) {
+				elem[ jQuery.expando ] = id = ++jQuery.uuid;
+			} else {
+				id = jQuery.expando;
+			}
+		}
+
+		if ( !cache[ id ] ) {
+			cache[ id ] = {};
+
+			// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
+			// metadata on plain JS objects when the object is serialized using
+			// JSON.stringify
+			if ( !isNode ) {
+				cache[ id ].toJSON = jQuery.noop;
+			}
+		}
+
+		// An object can be passed to jQuery.data instead of a key/value pair; this gets
+		// shallow copied over onto the existing cache
+		if ( typeof name === "object" || typeof name === "function" ) {
+			if ( pvt ) {
+				cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
+			} else {
+				cache[ id ] = jQuery.extend(cache[ id ], name);
+			}
+		}
+
+		thisCache = cache[ id ];
+
+		// Internal jQuery data is stored in a separate object inside the object's data
+		// cache in order to avoid key collisions between internal data and user-defined
+		// data
+		if ( pvt ) {
+			if ( !thisCache[ internalKey ] ) {
+				thisCache[ internalKey ] = {};
+			}
+
+			thisCache = thisCache[ internalKey ];
+		}
+
+		if ( data !== undefined ) {
+			thisCache[ jQuery.camelCase( name ) ] = data;
+		}
+
+		// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
+		// not attempt to inspect the internal events object using jQuery.data, as this
+		// internal data object is undocumented and subject to change.
+		if ( name === "events" && !thisCache[name] ) {
+			return thisCache[ internalKey ] && thisCache[ internalKey ].events;
+		}
+
+		return getByName ? 
+			// Check for both converted-to-camel and non-converted data property names
+			thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] :
+			thisCache;
+	},
+
+	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var internalKey = jQuery.expando, isNode = elem.nodeType,
+
+			// See jQuery.data for more information
+			cache = isNode ? jQuery.cache : elem,
+
+			// See jQuery.data for more information
+			id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+		// If there is already no cache entry for this object, there is no
+		// purpose in continuing
+		if ( !cache[ id ] ) {
+			return;
+		}
+
+		if ( name ) {
+			var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
+
+			if ( thisCache ) {
+				delete thisCache[ name ];
+
+				// If there is no data left in the cache, we want to continue
+				// and let the cache object itself get destroyed
+				if ( !isEmptyDataObject(thisCache) ) {
+					return;
+				}
+			}
+		}
+
+		// See jQuery.data for more information
+		if ( pvt ) {
+			delete cache[ id ][ internalKey ];
+
+			// Don't destroy the parent cache unless the internal data object
+			// had been the only thing left in it
+			if ( !isEmptyDataObject(cache[ id ]) ) {
+				return;
+			}
+		}
+
+		var internalCache = cache[ id ][ internalKey ];
+
+		// Browsers that fail expando deletion also refuse to delete expandos on
+		// the window, but it will allow it on all other JS objects; other browsers
+		// don't care
+		if ( jQuery.support.deleteExpando || cache != window ) {
+			delete cache[ id ];
+		} else {
+			cache[ id ] = null;
+		}
+
+		// We destroyed the entire user cache at once because it's faster than
+		// iterating through each key, but we need to continue to persist internal
+		// data if it existed
+		if ( internalCache ) {
+			cache[ id ] = {};
+			// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
+			// metadata on plain JS objects when the object is serialized using
+			// JSON.stringify
+			if ( !isNode ) {
+				cache[ id ].toJSON = jQuery.noop;
+			}
+
+			cache[ id ][ internalKey ] = internalCache;
+
+		// Otherwise, we need to eliminate the expando on the node to avoid
+		// false lookups in the cache for entries that no longer exist
+		} else if ( isNode ) {
+			// IE does not allow us to delete expando properties from nodes,
+			// nor does it have a removeAttribute function on Document nodes;
+			// we must handle all of these cases
+			if ( jQuery.support.deleteExpando ) {
+				delete elem[ jQuery.expando ];
+			} else if ( elem.removeAttribute ) {
+				elem.removeAttribute( jQuery.expando );
+			} else {
+				elem[ jQuery.expando ] = null;
+			}
+		}
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return jQuery.data( elem, name, data, true );
+	},
+
+	// A method for determining if a DOM node can handle the data expando
+	acceptData: function( elem ) {
+		if ( elem.nodeName ) {
+			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+			if ( match ) {
+				return !(match === true || elem.getAttribute("classid") !== match);
+			}
+		}
+
+		return true;
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var data = null;
+
+		if ( typeof key === "undefined" ) {
+			if ( this.length ) {
+				data = jQuery.data( this[0] );
+
+				if ( this[0].nodeType === 1 ) {
+			    var attr = this[0].attributes, name;
+					for ( var i = 0, l = attr.length; i < l; i++ ) {
+						name = attr[i].name;
+
+						if ( name.indexOf( "data-" ) === 0 ) {
+							name = jQuery.camelCase( name.substring(5) );
+
+							dataAttr( this[0], name, data[ name ] );
+						}
+					}
+				}
+			}
+
+			return data;
+
+		} else if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		var parts = key.split(".");
+		parts[1] = parts[1] ? "." + parts[1] : "";
+
+		if ( value === undefined ) {
+			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+			// Try to fetch any internally stored data first
+			if ( data === undefined && this.length ) {
+				data = jQuery.data( this[0], key );
+				data = dataAttr( this[0], key, data );
+			}
+
+			return data === undefined && parts[1] ?
+				this.data( parts[0] ) :
+				data;
+
+		} else {
+			return this.each(function() {
+				var $this = jQuery( this ),
+					args = [ parts[0], value ];
+
+				$this.triggerHandler( "setData" + parts[1] + "!", args );
+				jQuery.data( this, key, value );
+				$this.triggerHandler( "changeData" + parts[1] + "!", args );
+			});
+		}
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+		var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+				data === "false" ? false :
+				data === "null" ? null :
+				!jQuery.isNaN( data ) ? parseFloat( data ) :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
+// property to be considered empty objects; this property always exists in
+// order to make sure JSON.stringify does not expose internal metadata
+function isEmptyDataObject( obj ) {
+	for ( var name in obj ) {
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+	var deferDataKey = type + "defer",
+		queueDataKey = type + "queue",
+		markDataKey = type + "mark",
+		defer = jQuery.data( elem, deferDataKey, undefined, true );
+	if ( defer &&
+		( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
+		( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
+		// Give room for hard-coded callbacks to fire first
+		// and eventually mark/queue something else on the element
+		setTimeout( function() {
+			if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
+				!jQuery.data( elem, markDataKey, undefined, true ) ) {
+				jQuery.removeData( elem, deferDataKey, true );
+				defer.resolve();
+			}
+		}, 0 );
+	}
+}
+
+jQuery.extend({
+
+	_mark: function( elem, type ) {
+		if ( elem ) {
+			type = (type || "fx") + "mark";
+			jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
+		}
+	},
+
+	_unmark: function( force, elem, type ) {
+		if ( force !== true ) {
+			type = elem;
+			elem = force;
+			force = false;
+		}
+		if ( elem ) {
+			type = type || "fx";
+			var key = type + "mark",
+				count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
+			if ( count ) {
+				jQuery.data( elem, key, count, true );
+			} else {
+				jQuery.removeData( elem, key, true );
+				handleQueueMarkDefer( elem, type, "mark" );
+			}
+		}
+	},
+
+	queue: function( elem, type, data ) {
+		if ( elem ) {
+			type = (type || "fx") + "queue";
+			var q = jQuery.data( elem, type, undefined, true );
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !q || jQuery.isArray(data) ) {
+					q = jQuery.data( elem, type, jQuery.makeArray(data), true );
+				} else {
+					q.push( data );
+				}
+			}
+			return q || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			fn = queue.shift(),
+			defer;
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+		}
+
+		if ( fn ) {
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift("inprogress");
+			}
+
+			fn.call(elem, function() {
+				jQuery.dequeue(elem, type);
+			});
+		}
+
+		if ( !queue.length ) {
+			jQuery.removeData( elem, type + "queue", true );
+			handleQueueMarkDefer( elem, type, "queue" );
+		}
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+		}
+
+		if ( data === undefined ) {
+			return jQuery.queue( this[0], type );
+		}
+		return this.each(function() {
+			var queue = jQuery.queue( this, type, data );
+
+			if ( type === "fx" && queue[0] !== "inprogress" ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	// Based off of the plugin by Clint Helfers, with permission.
+	// http://blindsignals.com/index.php/2009/07/jquery-delay/
+	delay: function( time, type ) {
+		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+		type = type || "fx";
+
+		return this.queue( type, function() {
+			var elem = this;
+			setTimeout(function() {
+				jQuery.dequeue( elem, type );
+			}, time );
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, object ) {
+		if ( typeof type !== "string" ) {
+			object = type;
+			type = undefined;
+		}
+		type = type || "fx";
+		var defer = jQuery.Deferred(),
+			elements = this,
+			i = elements.length,
+			count = 1,
+			deferDataKey = type + "defer",
+			queueDataKey = type + "queue",
+			markDataKey = type + "mark",
+			tmp;
+		function resolve() {
+			if ( !( --count ) ) {
+				defer.resolveWith( elements, [ elements ] );
+			}
+		}
+		while( i-- ) {
+			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+					jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
+				count++;
+				tmp.done( resolve );
+			}
+		}
+		resolve();
+		return defer.promise();
+	}
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+	rspace = /\s+/,
+	rreturn = /\r/g,
+	rtype = /^(?:button|input)$/i,
+	rfocusable = /^(?:button|input|object|select|textarea)$/i,
+	rclickable = /^a(?:rea)?$/i,
+	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+	rinvalidChar = /\:|^on/,
+	formHook, boolHook;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return jQuery.access( this, name, value, true, jQuery.attr );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	},
+	
+	prop: function( name, value ) {
+		return jQuery.access( this, name, value, true, jQuery.prop );
+	},
+	
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	},
+
+	addClass: function( value ) {
+		var classNames, i, l, elem,
+			setClass, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( value && typeof value === "string" ) {
+			classNames = value.split( rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 ) {
+					if ( !elem.className && classNames.length === 1 ) {
+						elem.className = value;
+
+					} else {
+						setClass = " " + elem.className + " ";
+
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+								setClass += classNames[ c ] + " ";
+							}
+						}
+						elem.className = jQuery.trim( setClass );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classNames, i, l, elem, className, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( (value && typeof value === "string") || value === undefined ) {
+			classNames = (value || "").split( rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 && elem.className ) {
+					if ( value ) {
+						className = (" " + elem.className + " ").replace( rclass, " " );
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							className = className.replace(" " + classNames[ c ] + " ", " ");
+						}
+						elem.className = jQuery.trim( className );
+
+					} else {
+						elem.className = "";
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value,
+			isBool = typeof stateVal === "boolean";
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					state = stateVal,
+					classNames = value.split( rspace );
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space seperated list
+					state = isBool ? state : !self.hasClass( className );
+					self[ state ? "addClass" : "removeClass" ]( className );
+				}
+
+			} else if ( type === "undefined" || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// toggle whole className
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ";
+		for ( var i = 0, l = this.length; i < l; i++ ) {
+			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+				return true;
+			}
+		}
+
+		return false;
+	},
+
+	val: function( value ) {
+		var hooks, ret,
+			elem = this[0];
+		
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ? 
+					// handle most common string cases
+					ret.replace(rreturn, "") : 
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return undefined;
+		}
+
+		var isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var self = jQuery(this), val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, self.val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map(val, function ( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				// attributes.value is undefined in Blackberry 4.7 but
+				// uses .value. See #6932
+				var val = elem.attributes.value;
+				return !val || val.specified ? elem.value : elem.text;
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value,
+					index = elem.selectedIndex,
+					values = [],
+					options = elem.options,
+					one = elem.type === "select-one";
+
+				// Nothing was selected
+				if ( index < 0 ) {
+					return null;
+				}
+
+				// Loop through all the selected options
+				for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+					var option = options[ i ];
+
+					// Don't return options that are disabled or in a disabled optgroup
+					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+				if ( one && !values.length && options.length ) {
+					return jQuery( options[ index ] ).val();
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var values = jQuery.makeArray( value );
+
+				jQuery(elem).find("option").each(function() {
+					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+				});
+
+				if ( !values.length ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	},
+
+	attrFn: {
+		val: true,
+		css: true,
+		html: true,
+		text: true,
+		data: true,
+		width: true,
+		height: true,
+		offset: true
+	},
+	
+	attrFix: {
+		// Always normalize to ensure hook usage
+		tabindex: "tabIndex"
+	},
+	
+	attr: function( elem, name, value, pass ) {
+		var nType = elem.nodeType;
+		
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return undefined;
+		}
+
+		if ( pass && name in jQuery.attrFn ) {
+			return jQuery( elem )[ name ]( value );
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( !("getAttribute" in elem) ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		var ret, hooks,
+			notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		// Normalize the name if needed
+		if ( notxml ) {
+			name = jQuery.attrFix[ name ] || name;
+
+			hooks = jQuery.attrHooks[ name ];
+
+			if ( !hooks ) {
+				// Use boolHook for boolean attributes
+				if ( rboolean.test( name ) ) {
+
+					hooks = boolHook;
+
+				// Use formHook for forms and if the name contains certain characters
+				} else if ( formHook && name !== "className" &&
+					(jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) {
+
+					hooks = formHook;
+				}
+			}
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+				return undefined;
+
+			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, "" + value );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+
+			ret = elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret === null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, name ) {
+		var propName;
+		if ( elem.nodeType === 1 ) {
+			name = jQuery.attrFix[ name ] || name;
+		
+			if ( jQuery.support.getSetAttribute ) {
+				// Use removeAttribute in browsers that support it
+				elem.removeAttribute( name );
+			} else {
+				jQuery.attr( elem, name, "" );
+				elem.removeAttributeNode( elem.getAttributeNode( name ) );
+			}
+
+			// Set corresponding property to false for boolean attributes
+			if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {
+				elem[ propName ] = false;
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+					jQuery.error( "type property can't be changed" );
+				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to it's default in case type is set after value
+					// This is for element creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		},
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				var attributeNode = elem.getAttributeNode("tabIndex");
+
+				return attributeNode && attributeNode.specified ?
+					parseInt( attributeNode.value, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						undefined;
+			}
+		},
+		// Use the value property for back compat
+		// Use the formHook for button elements in IE6/7 (#1954)
+		value: {
+			get: function( elem, name ) {
+				if ( formHook && jQuery.nodeName( elem, "button" ) ) {
+					return formHook.get( elem, name );
+				}
+				return name in elem ?
+					elem.value :
+					null;
+			},
+			set: function( elem, value, name ) {
+				if ( formHook && jQuery.nodeName( elem, "button" ) ) {
+					return formHook.set( elem, value, name );
+				}
+				// Does not return so that setAttribute is also used
+				elem.value = value;
+			}
+		}
+	},
+
+	propFix: {
+		tabindex: "tabIndex",
+		readonly: "readOnly",
+		"for": "htmlFor",
+		"class": "className",
+		maxlength: "maxLength",
+		cellspacing: "cellSpacing",
+		cellpadding: "cellPadding",
+		rowspan: "rowSpan",
+		colspan: "colSpan",
+		usemap: "useMap",
+		frameborder: "frameBorder",
+		contenteditable: "contentEditable"
+	},
+	
+	prop: function( elem, name, value ) {
+		var nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return undefined;
+		}
+
+		var ret, hooks,
+			notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				return (elem[ name ] = value);
+			}
+
+		} else {
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				return elem[ name ];
+			}
+		}
+	},
+	
+	propHooks: {}
+});
+
+// Hook for boolean attributes
+boolHook = {
+	get: function( elem, name ) {
+		// Align boolean attributes with corresponding properties
+		return jQuery.prop( elem, name ) ?
+			name.toLowerCase() :
+			undefined;
+	},
+	set: function( elem, value, name ) {
+		var propName;
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			// value is true since we know at this point it's type boolean and not false
+			// Set boolean attributes to the same name and set the DOM property
+			propName = jQuery.propFix[ name ] || name;
+			if ( propName in elem ) {
+				// Only set the IDL specifically if it already exists on the element
+				elem[ propName ] = true;
+			}
+
+			elem.setAttribute( name, name.toLowerCase() );
+		}
+		return name;
+	}
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !jQuery.support.getSetAttribute ) {
+
+	// propFix is more comprehensive and contains all fixes
+	jQuery.attrFix = jQuery.propFix;
+	
+	// Use this for any attribute on a form in IE6/7
+	formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret;
+			ret = elem.getAttributeNode( name );
+			// Return undefined if nodeValue is empty string
+			return ret && ret.nodeValue !== "" ?
+				ret.nodeValue :
+				undefined;
+		},
+		set: function( elem, value, name ) {
+			// Check form objects in IE (multiple bugs related)
+			// Only use nodeValue if the attribute node exists on the form
+			var ret = elem.getAttributeNode( name );
+			if ( ret ) {
+				ret.nodeValue = value;
+				return value;
+			}
+		}
+	};
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		});
+	});
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			get: function( elem ) {
+				var ret = elem.getAttribute( name, 2 );
+				return ret === null ? undefined : ret;
+			}
+		});
+	});
+}
+
+if ( !jQuery.support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Normalize to lowercase since IE uppercases css property names
+			return elem.style.cssText.toLowerCase() || undefined;
+		},
+		set: function( elem, value ) {
+			return (elem.style.cssText = "" + value);
+		}
+	};
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+		}
+	});
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+	jQuery.each([ "radio", "checkbox" ], function() {
+		jQuery.valHooks[ this ] = {
+			get: function( elem ) {
+				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+				return elem.getAttribute("value") === null ? "on" : elem.value;
+			}
+		};
+	});
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);
+			}
+		}
+	});
+});
+
+
+
+
+var rnamespaces = /\.(.*)$/,
+	rformElems = /^(?:textarea|input|select)$/i,
+	rperiod = /\./g,
+	rspaces = / /g,
+	rescape = /[^\w\s.|`]/g,
+	fcleanup = function( nm ) {
+		return nm.replace(rescape, "\\$&");
+	};
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function( elem, types, handler, data ) {
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		if ( handler === false ) {
+			handler = returnFalse;
+		} else if ( !handler ) {
+			// Fixes bug #7229. Fix recommended by jdalton
+			return;
+		}
+
+		var handleObjIn, handleObj;
+
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+		}
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure
+		var elemData = jQuery._data( elem );
+
+		// If no elemData is found then we must be trying to bind to one of the
+		// banned noData elements
+		if ( !elemData ) {
+			return;
+		}
+
+		var events = elemData.events,
+			eventHandle = elemData.handle;
+
+		if ( !events ) {
+			elemData.events = events = {};
+		}
+
+		if ( !eventHandle ) {
+			elemData.handle = eventHandle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+		}
+
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native events in IE.
+		eventHandle.elem = elem;
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		types = types.split(" ");
+
+		var type, i = 0, namespaces;
+
+		while ( (type = types[ i++ ]) ) {
+			handleObj = handleObjIn ?
+				jQuery.extend({}, handleObjIn) :
+				{ handler: handler, data: data };
+
+			// Namespaced event handlers
+			if ( type.indexOf(".") > -1 ) {
+				namespaces = type.split(".");
+				type = namespaces.shift();
+				handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+			} else {
+				namespaces = [];
+				handleObj.namespace = "";
+			}
+
+			handleObj.type = type;
+			if ( !handleObj.guid ) {
+				handleObj.guid = handler.guid;
+			}
+
+			// Get the current list of functions bound to this event
+			var handlers = events[ type ],
+				special = jQuery.event.special[ type ] || {};
+
+			// Init the event handler queue
+			if ( !handlers ) {
+				handlers = events[ type ] = [];
+
+				// Check for a special event handler
+				// Only use addEventListener/attachEvent if the special
+				// events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add the function to the element's handler list
+			handlers.push( handleObj );
+
+			// Keep track of which events have been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, pos ) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		if ( handler === false ) {
+			handler = returnFalse;
+		}
+
+		var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+			elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+			events = elemData && elemData.events;
+
+		if ( !elemData || !events ) {
+			return;
+		}
+
+		// types is actually an event object here
+		if ( types && types.type ) {
+			handler = types.handler;
+			types = types.type;
+		}
+
+		// Unbind all events for the element
+		if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
+			types = types || "";
+
+			for ( type in events ) {
+				jQuery.event.remove( elem, type + types );
+			}
+
+			return;
+		}
+
+		// Handle multiple events separated by a space
+		// jQuery(...).unbind("mouseover mouseout", fn);
+		types = types.split(" ");
+
+		while ( (type = types[ i++ ]) ) {
+			origType = type;
+			handleObj = null;
+			all = type.indexOf(".") < 0;
+			namespaces = [];
+
+			if ( !all ) {
+				// Namespaced event handlers
+				namespaces = type.split(".");
+				type = namespaces.shift();
+
+				namespace = new RegExp("(^|\\.)" +
+					jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
+			}
+
+			eventType = events[ type ];
+
+			if ( !eventType ) {
+				continue;
+			}
+
+			if ( !handler ) {
+				for ( j = 0; j < eventType.length; j++ ) {
+					handleObj = eventType[ j ];
+
+					if ( all || namespace.test( handleObj.namespace ) ) {
+						jQuery.event.remove( elem, origType, handleObj.handler, j );
+						eventType.splice( j--, 1 );
+					}
+				}
+
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+
+			for ( j = pos || 0; j < eventType.length; j++ ) {
+				handleObj = eventType[ j ];
+
+				if ( handler.guid === handleObj.guid ) {
+					// remove the given handler for the given type
+					if ( all || namespace.test( handleObj.namespace ) ) {
+						if ( pos == null ) {
+							eventType.splice( j--, 1 );
+						}
+
+						if ( special.remove ) {
+							special.remove.call( elem, handleObj );
+						}
+					}
+
+					if ( pos != null ) {
+						break;
+					}
+				}
+			}
+
+			// remove generic event handler if no more handlers exist
+			if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				ret = null;
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			var handle = elemData.handle;
+			if ( handle ) {
+				handle.elem = null;
+			}
+
+			delete elemData.events;
+			delete elemData.handle;
+
+			if ( jQuery.isEmptyObject( elemData ) ) {
+				jQuery.removeData( elem, undefined, true );
+			}
+		}
+	},
+	
+	// Events that are safe to short-circuit if no handlers are attached.
+	// Native DOM events should not be added, they may have inline handlers.
+	customEvent: {
+		"getData": true,
+		"setData": true,
+		"changeData": true
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		// Event object or event type
+		var type = event.type || event,
+			namespaces = [],
+			exclusive;
+
+		if ( type.indexOf("!") >= 0 ) {
+			// Exclusive events trigger only for the exact event (no namespaces)
+			type = type.slice(0, -1);
+			exclusive = true;
+		}
+
+		if ( type.indexOf(".") >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+
+		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+			// No jQuery handlers for this event type, and it can't have inline handlers
+			return;
+		}
+
+		// Caller can pass in an Event, Object, or just an event type string
+		event = typeof event === "object" ?
+			// jQuery.Event object
+			event[ jQuery.expando ] ? event :
+			// Object literal
+			new jQuery.Event( type, event ) :
+			// Just the event type (string)
+			new jQuery.Event( type );
+
+		event.type = type;
+		event.exclusive = exclusive;
+		event.namespace = namespaces.join(".");
+		event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
+		
+		// triggerHandler() and global events don't bubble or run the default action
+		if ( onlyHandlers || !elem ) {
+			event.preventDefault();
+			event.stopPropagation();
+		}
+
+		// Handle a global trigger
+		if ( !elem ) {
+			// TODO: Stop taunting the data cache; remove global events and always attach to document
+			jQuery.each( jQuery.cache, function() {
+				// internalKey variable is just used to make it easier to find
+				// and potentially change this stuff later; currently it just
+				// points to jQuery.expando
+				var internalKey = jQuery.expando,
+					internalCache = this[ internalKey ];
+				if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
+					jQuery.event.trigger( event, data, internalCache.handle.elem );
+				}
+			});
+			return;
+		}
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		event.target = elem;
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data != null ? jQuery.makeArray( data ) : [];
+		data.unshift( event );
+
+		var cur = elem,
+			// IE doesn't like method names with a colon (#3533, #8272)
+			ontype = type.indexOf(":") < 0 ? "on" + type : "";
+
+		// Fire event on the current element, then bubble up the DOM tree
+		do {
+			var handle = jQuery._data( cur, "handle" );
+
+			event.currentTarget = cur;
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Trigger an inline bound script
+			if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
+				event.result = false;
+				event.preventDefault();
+			}
+
+			// Bubble up to document, then to window
+			cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
+		} while ( cur && !event.isPropagationStopped() );
+
+		// If nobody prevented the default action, do it now
+		if ( !event.isDefaultPrevented() ) {
+			var old,
+				special = jQuery.event.special[ type ] || {};
+
+			if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
+				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Can't use an .isFunction)() check here because IE6/7 fails that test.
+				// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
+				try {
+					if ( ontype && elem[ type ] ) {
+						// Don't re-trigger an onFOO event when we call its FOO() method
+						old = elem[ ontype ];
+
+						if ( old ) {
+							elem[ ontype ] = null;
+						}
+
+						jQuery.event.triggered = type;
+						elem[ type ]();
+					}
+				} catch ( ieError ) {}
+
+				if ( old ) {
+					elem[ ontype ] = old;
+				}
+
+				jQuery.event.triggered = undefined;
+			}
+		}
+		
+		return event.result;
+	},
+
+	handle: function( event ) {
+		event = jQuery.event.fix( event || window.event );
+		// Snapshot the handlers list since a called handler may add/remove events.
+		var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
+			run_all = !event.exclusive && !event.namespace,
+			args = Array.prototype.slice.call( arguments, 0 );
+
+		// Use the fix-ed Event rather than the (read-only) native event
+		args[0] = event;
+		event.currentTarget = this;
+
+		for ( var j = 0, l = handlers.length; j < l; j++ ) {
+			var handleObj = handlers[ j ];
+
+			// Triggered event must 1) be non-exclusive and have no namespace, or
+			// 2) have namespace(s) a subset or equal to those in the bound event.
+			if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
+				// Pass in a reference to the handler function itself
+				// So that we can later remove it
+				event.handler = handleObj.handler;
+				event.data = handleObj.data;
+				event.handleObj = handleObj;
+
+				var ret = handleObj.handler.apply( this, args );
+
+				if ( ret !== undefined ) {
+					event.result = ret;
+					if ( ret === false ) {
+						event.preventDefault();
+						event.stopPropagation();
+					}
+				}
+
+				if ( event.isImmediatePropagationStopped() ) {
+					break;
+				}
+			}
+		}
+		return event.result;
+	},
+
+	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// store a copy of the original event object
+		// and "clone" to set read-only properties
+		var originalEvent = event;
+		event = jQuery.Event( originalEvent );
+
+		for ( var i = this.props.length, prop; i; ) {
+			prop = this.props[ --i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Fix target property, if necessary
+		if ( !event.target ) {
+			// Fixes #1925 where srcElement might not be defined either
+			event.target = event.srcElement || document;
+		}
+
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement ) {
+			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
+		}
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var eventDocument = event.target.ownerDocument || document,
+				doc = eventDocument.documentElement,
+				body = eventDocument.body;
+
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
+		}
+
+		// Add which for key events
+		if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
+			event.which = event.charCode != null ? event.charCode : event.keyCode;
+		}
+
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey ) {
+			event.metaKey = event.ctrlKey;
+		}
+
+		// Add which for click: 1 === left; 2 === middle; 3 === right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button !== undefined ) {
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+		}
+
+		return event;
+	},
+
+	// Deprecated, use jQuery.guid instead
+	guid: 1E8,
+
+	// Deprecated, use jQuery.proxy instead
+	proxy: jQuery.proxy,
+
+	special: {
+		ready: {
+			// Make sure the ready event is setup
+			setup: jQuery.bindReady,
+			teardown: jQuery.noop
+		},
+
+		live: {
+			add: function( handleObj ) {
+				jQuery.event.add( this,
+					liveConvert( handleObj.origType, handleObj.selector ),
+					jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
+			},
+
+			remove: function( handleObj ) {
+				jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
+			}
+		},
+
+		beforeunload: {
+			setup: function( data, namespaces, eventHandle ) {
+				// We only want to do this special case on windows
+				if ( jQuery.isWindow( this ) ) {
+					this.onbeforeunload = eventHandle;
+				}
+			},
+
+			teardown: function( namespaces, eventHandle ) {
+				if ( this.onbeforeunload === eventHandle ) {
+					this.onbeforeunload = null;
+				}
+			}
+		}
+	}
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} :
+	function( elem, type, handle ) {
+		if ( elem.detachEvent ) {
+			elem.detachEvent( "on" + type, handle );
+		}
+	};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !this.preventDefault ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
+			src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// timeStamp is buggy for some events on Firefox(#3843)
+	// So we won't rely on the native value
+	this.timeStamp = jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+	return false;
+}
+function returnTrue() {
+	return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	preventDefault: function() {
+		this.isDefaultPrevented = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+
+		// if preventDefault exists run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// otherwise set the returnValue property of the original event to false (IE)
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		this.isPropagationStopped = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+		// if stopPropagation exists run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+		// otherwise set the cancelBubble property of the original event to true (IE)
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	},
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse
+};
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+
+	// Check if mouse(over|out) are still within the same parent element
+	var related = event.relatedTarget,
+		inside = false,
+		eventType = event.type;
+
+	event.type = event.data;
+
+	if ( related !== this ) {
+
+		if ( related ) {
+			inside = jQuery.contains( this, related );
+		}
+
+		if ( !inside ) {
+
+			jQuery.event.handle.apply( this, arguments );
+
+			event.type = eventType;
+		}
+	}
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+	event.type = event.data;
+	jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		setup: function( data ) {
+			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
+		},
+		teardown: function( data ) {
+			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+		}
+	};
+});
+
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function( data, namespaces ) {
+			if ( !jQuery.nodeName( this, "form" ) ) {
+				jQuery.event.add(this, "click.specialSubmit", function( e ) {
+					var elem = e.target,
+						type = elem.type;
+
+					if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+						trigger( "submit", this, arguments );
+					}
+				});
+
+				jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+					var elem = e.target,
+						type = elem.type;
+
+					if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+						trigger( "submit", this, arguments );
+					}
+				});
+
+			} else {
+				return false;
+			}
+		},
+
+		teardown: function( namespaces ) {
+			jQuery.event.remove( this, ".specialSubmit" );
+		}
+	};
+
+}
+
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
+
+	var changeFilters,
+
+	getVal = function( elem ) {
+		var type = elem.type, val = elem.value;
+
+		if ( type === "radio" || type === "checkbox" ) {
+			val = elem.checked;
+
+		} else if ( type === "select-multiple" ) {
+			val = elem.selectedIndex > -1 ?
+				jQuery.map( elem.options, function( elem ) {
+					return elem.selected;
+				}).join("-") :
+				"";
+
+		} else if ( jQuery.nodeName( elem, "select" ) ) {
+			val = elem.selectedIndex;
+		}
+
+		return val;
+	},
+
+	testChange = function testChange( e ) {
+		var elem = e.target, data, val;
+
+		if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
+			return;
+		}
+
+		data = jQuery._data( elem, "_change_data" );
+		val = getVal(elem);
+
+		// the current data will be also retrieved by beforeactivate
+		if ( e.type !== "focusout" || elem.type !== "radio" ) {
+			jQuery._data( elem, "_change_data", val );
+		}
+
+		if ( data === undefined || val === data ) {
+			return;
+		}
+
+		if ( data != null || val ) {
+			e.type = "change";
+			e.liveFired = undefined;
+			jQuery.event.trigger( e, arguments[1], elem );
+		}
+	};
+
+	jQuery.event.special.change = {
+		filters: {
+			focusout: testChange,
+
+			beforedeactivate: testChange,
+
+			click: function( e ) {
+				var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
+
+				if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
+					testChange.call( this, e );
+				}
+			},
+
+			// Change has to be called before submit
+			// Keydown will be called before keypress, which is used in submit-event delegation
+			keydown: function( e ) {
+				var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
+
+				if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
+					(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+					type === "select-multiple" ) {
+					testChange.call( this, e );
+				}
+			},
+
+			// Beforeactivate happens also before the previous element is blurred
+			// with this event you can't trigger a change event, but you can store
+			// information
+			beforeactivate: function( e ) {
+				var elem = e.target;
+				jQuery._data( elem, "_change_data", getVal(elem) );
+			}
+		},
+
+		setup: function( data, namespaces ) {
+			if ( this.type === "file" ) {
+				return false;
+			}
+
+			for ( var type in changeFilters ) {
+				jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+			}
+
+			return rformElems.test( this.nodeName );
+		},
+
+		teardown: function( namespaces ) {
+			jQuery.event.remove( this, ".specialChange" );
+
+			return rformElems.test( this.nodeName );
+		}
+	};
+
+	changeFilters = jQuery.event.special.change.filters;
+
+	// Handle when the input is .focus()'d
+	changeFilters.focus = changeFilters.beforeactivate;
+}
+
+function trigger( type, elem, args ) {
+	// Piggyback on a donor event to simulate a different one.
+	// Fake originalEvent to avoid donor's stopPropagation, but if the
+	// simulated event prevents default then we do the same on the donor.
+	// Don't pass args or remember liveFired; they apply to the donor event.
+	var event = jQuery.extend( {}, args[ 0 ] );
+	event.type = type;
+	event.originalEvent = {};
+	event.liveFired = undefined;
+	jQuery.event.handle.call( elem, event );
+	if ( event.isDefaultPrevented() ) {
+		args[ 0 ].preventDefault();
+	}
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler while someone wants focusin/focusout
+		var attaches = 0;
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				if ( attaches++ === 0 ) {
+					document.addEventListener( orig, handler, true );
+				}
+			},
+			teardown: function() {
+				if ( --attaches === 0 ) {
+					document.removeEventListener( orig, handler, true );
+				}
+			}
+		};
+
+		function handler( donor ) {
+			// Donor event is always a native one; fix it and switch its type.
+			// Let focusin/out handler cancel the donor focus/blur event.
+			var e = jQuery.event.fix( donor );
+			e.type = fix;
+			e.originalEvent = {};
+			jQuery.event.trigger( e, null, e.target );
+			if ( e.isDefaultPrevented() ) {
+				donor.preventDefault();
+			}
+		}
+	});
+}
+
+jQuery.each(["bind", "one"], function( i, name ) {
+	jQuery.fn[ name ] = function( type, data, fn ) {
+		var handler;
+
+		// Handle object literals
+		if ( typeof type === "object" ) {
+			for ( var key in type ) {
+				this[ name ](key, data, type[key], fn);
+			}
+			return this;
+		}
+
+		if ( arguments.length === 2 || data === false ) {
+			fn = data;
+			data = undefined;
+		}
+
+		if ( name === "one" ) {
+			handler = function( event ) {
+				jQuery( this ).unbind( event, handler );
+				return fn.apply( this, arguments );
+			};
+			handler.guid = fn.guid || jQuery.guid++;
+		} else {
+			handler = fn;
+		}
+
+		if ( type === "unload" && name !== "one" ) {
+			this.one( type, data, fn );
+
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				jQuery.event.add( this[i], type, handler, data );
+			}
+		}
+
+		return this;
+	};
+});
+
+jQuery.fn.extend({
+	unbind: function( type, fn ) {
+		// Handle object literals
+		if ( typeof type === "object" && !type.preventDefault ) {
+			for ( var key in type ) {
+				this.unbind(key, type[key]);
+			}
+
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				jQuery.event.remove( this[i], type, fn );
+			}
+		}
+
+		return this;
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.live( types, data, fn, selector );
+	},
+
+	undelegate: function( selector, types, fn ) {
+		if ( arguments.length === 0 ) {
+			return this.unbind( "live" );
+
+		} else {
+			return this.die( types, null, fn, selector );
+		}
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+
+	triggerHandler: function( type, data ) {
+		if ( this[0] ) {
+			return jQuery.event.trigger( type, data, this[0], true );
+		}
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments,
+			guid = fn.guid || jQuery.guid++,
+			i = 0,
+			toggler = function( event ) {
+				// Figure out which function to execute
+				var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+				jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+				// Make sure that clicks stop
+				event.preventDefault();
+
+				// and execute the function
+				return args[ lastToggle ].apply( this, arguments ) || false;
+			};
+
+		// link all the functions, so any of them can unbind this click handler
+		toggler.guid = guid;
+		while ( i < args.length ) {
+			args[ i++ ].guid = guid;
+		}
+
+		return this.click( toggler );
+	},
+
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	}
+});
+
+var liveMap = {
+	focus: "focusin",
+	blur: "focusout",
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+	jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+		var type, i = 0, match, namespaces, preType,
+			selector = origSelector || this.selector,
+			context = origSelector ? this : jQuery( this.context );
+
+		if ( typeof types === "object" && !types.preventDefault ) {
+			for ( var key in types ) {
+				context[ name ]( key, data, types[key], selector );
+			}
+
+			return this;
+		}
+
+		if ( name === "die" && !types &&
+					origSelector && origSelector.charAt(0) === "." ) {
+
+			context.unbind( origSelector );
+
+			return this;
+		}
+
+		if ( data === false || jQuery.isFunction( data ) ) {
+			fn = data || returnFalse;
+			data = undefined;
+		}
+
+		types = (types || "").split(" ");
+
+		while ( (type = types[ i++ ]) != null ) {
+			match = rnamespaces.exec( type );
+			namespaces = "";
+
+			if ( match )  {
+				namespaces = match[0];
+				type = type.replace( rnamespaces, "" );
+			}
+
+			if ( type === "hover" ) {
+				types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+				continue;
+			}
+
+			preType = type;
+
+			if ( liveMap[ type ] ) {
+				types.push( liveMap[ type ] + namespaces );
+				type = type + namespaces;
+
+			} else {
+				type = (liveMap[ type ] || type) + namespaces;
+			}
+
+			if ( name === "live" ) {
+				// bind live handler
+				for ( var j = 0, l = context.length; j < l; j++ ) {
+					jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
+						{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+				}
+
+			} else {
+				// unbind live handler
+				context.unbind( "live." + liveConvert( type, selector ), fn );
+			}
+		}
+
+		return this;
+	};
+});
+
+function liveHandler( event ) {
+	var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
+		elems = [],
+		selectors = [],
+		events = jQuery._data( this, "events" );
+
+	// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
+	if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
+		return;
+	}
+
+	if ( event.namespace ) {
+		namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
+	}
+
+	event.liveFired = this;
+
+	var live = events.live.slice(0);
+
+	for ( j = 0; j < live.length; j++ ) {
+		handleObj = live[j];
+
+		if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+			selectors.push( handleObj.selector );
+
+		} else {
+			live.splice( j--, 1 );
+		}
+	}
+
+	match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+	for ( i = 0, l = match.length; i < l; i++ ) {
+		close = match[i];
+
+		for ( j = 0; j < live.length; j++ ) {
+			handleObj = live[j];
+
+			if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
+				elem = close.elem;
+				related = null;
+
+				// Those two events require additional checking
+				if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+					event.type = handleObj.preType;
+					related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+
+					// Make sure not to accidentally match a child element with the same selector
+					if ( related && jQuery.contains( elem, related ) ) {
+						related = elem;
+					}
+				}
+
+				if ( !related || related !== elem ) {
+					elems.push({ elem: elem, handleObj: handleObj, level: close.level });
+				}
+			}
+		}
+	}
+
+	for ( i = 0, l = elems.length; i < l; i++ ) {
+		match = elems[i];
+
+		if ( maxLevel && match.level > maxLevel ) {
+			break;
+		}
+
+		event.currentTarget = match.elem;
+		event.data = match.handleObj.data;
+		event.handleObj = match.handleObj;
+
+		ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+		if ( ret === false || event.isPropagationStopped() ) {
+			maxLevel = match.level;
+
+			if ( ret === false ) {
+				stop = false;
+			}
+			if ( event.isImmediatePropagationStopped() ) {
+				break;
+			}
+		}
+	}
+
+	return stop;
+}
+
+function liveConvert( type, selector ) {
+	return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		if ( fn == null ) {
+			fn = data;
+			data = null;
+		}
+
+		return arguments.length > 0 ?
+			this.bind( name, data, fn ) :
+			this.trigger( name );
+	};
+
+	if ( jQuery.attrFn ) {
+		jQuery.attrFn[ name ] = true;
+	}
+});
+
+
+
+/*!
+ * Sizzle CSS Selector Engine
+ *  Copyright 2011, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+	done = 0,
+	toString = Object.prototype.toString,
+	hasDuplicate = false,
+	baseHasDuplicate = true,
+	rBackslash = /\\/g,
+	rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+//   Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+	baseHasDuplicate = false;
+	return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+	results = results || [];
+	context = context || document;
+
+	var origContext = context;
+
+	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+		return [];
+	}
+	
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	var m, set, checkSet, extra, ret, cur, pop, i,
+		prune = true,
+		contextXML = Sizzle.isXML( context ),
+		parts = [],
+		soFar = selector;
+	
+	// Reset the position of the chunker regexp (start from head)
+	do {
+		chunker.exec( "" );
+		m = chunker.exec( soFar );
+
+		if ( m ) {
+			soFar = m[3];
+		
+			parts.push( m[1] );
+		
+			if ( m[2] ) {
+				extra = m[3];
+				break;
+			}
+		}
+	} while ( m );
+
+	if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+			set = posProcess( parts[0] + parts[1], context );
+
+		} else {
+			set = Expr.relative[ parts[0] ] ?
+				[ context ] :
+				Sizzle( parts.shift(), context );
+
+			while ( parts.length ) {
+				selector = parts.shift();
+
+				if ( Expr.relative[ selector ] ) {
+					selector += parts.shift();
+				}
+				
+				set = posProcess( selector, set );
+			}
+		}
+
+	} else {
+		// Take a shortcut and set the context if the root selector is an ID
+		// (but not if it'll be faster if the inner selector is an ID)
+		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+			ret = Sizzle.find( parts.shift(), context, contextXML );
+			context = ret.expr ?
+				Sizzle.filter( ret.expr, ret.set )[0] :
+				ret.set[0];
+		}
+
+		if ( context ) {
+			ret = seed ?
+				{ expr: parts.pop(), set: makeArray(seed) } :
+				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+			set = ret.expr ?
+				Sizzle.filter( ret.expr, ret.set ) :
+				ret.set;
+
+			if ( parts.length > 0 ) {
+				checkSet = makeArray( set );
+
+			} else {
+				prune = false;
+			}
+
+			while ( parts.length ) {
+				cur = parts.pop();
+				pop = cur;
+
+				if ( !Expr.relative[ cur ] ) {
+					cur = "";
+				} else {
+					pop = parts.pop();
+				}
+
+				if ( pop == null ) {
+					pop = context;
+				}
+
+				Expr.relative[ cur ]( checkSet, pop, contextXML );
+			}
+
+		} else {
+			checkSet = parts = [];
+		}
+	}
+
+	if ( !checkSet ) {
+		checkSet = set;
+	}
+
+	if ( !checkSet ) {
+		Sizzle.error( cur || selector );
+	}
+
+	if ( toString.call(checkSet) === "[object Array]" ) {
+		if ( !prune ) {
+			results.push.apply( results, checkSet );
+
+		} else if ( context && context.nodeType === 1 ) {
+			for ( i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+					results.push( set[i] );
+				}
+			}
+
+		} else {
+			for ( i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+					results.push( set[i] );
+				}
+			}
+		}
+
+	} else {
+		makeArray( checkSet, results );
+	}
+
+	if ( extra ) {
+		Sizzle( extra, origContext, results, seed );
+		Sizzle.uniqueSort( results );
+	}
+
+	return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+	if ( sortOrder ) {
+		hasDuplicate = baseHasDuplicate;
+		results.sort( sortOrder );
+
+		if ( hasDuplicate ) {
+			for ( var i = 1; i < results.length; i++ ) {
+				if ( results[i] === results[ i - 1 ] ) {
+					results.splice( i--, 1 );
+				}
+			}
+		}
+	}
+
+	return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+	return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+	return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+	var set;
+
+	if ( !expr ) {
+		return [];
+	}
+
+	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+		var match,
+			type = Expr.order[i];
+		
+		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+			var left = match[1];
+			match.splice( 1, 1 );
+
+			if ( left.substr( left.length - 1 ) !== "\\" ) {
+				match[1] = (match[1] || "").replace( rBackslash, "" );
+				set = Expr.find[ type ]( match, context, isXML );
+
+				if ( set != null ) {
+					expr = expr.replace( Expr.match[ type ], "" );
+					break;
+				}
+			}
+		}
+	}
+
+	if ( !set ) {
+		set = typeof context.getElementsByTagName !== "undefined" ?
+			context.getElementsByTagName( "*" ) :
+			[];
+	}
+
+	return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+	var match, anyFound,
+		old = expr,
+		result = [],
+		curLoop = set,
+		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+	while ( expr && set.length ) {
+		for ( var type in Expr.filter ) {
+			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+				var found, item,
+					filter = Expr.filter[ type ],
+					left = match[1];
+
+				anyFound = false;
+
+				match.splice(1,1);
+
+				if ( left.substr( left.length - 1 ) === "\\" ) {
+					continue;
+				}
+
+				if ( curLoop === result ) {
+					result = [];
+				}
+
+				if ( Expr.preFilter[ type ] ) {
+					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+					if ( !match ) {
+						anyFound = found = true;
+
+					} else if ( match === true ) {
+						continue;
+					}
+				}
+
+				if ( match ) {
+					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+						if ( item ) {
+							found = filter( item, match, i, curLoop );
+							var pass = not ^ !!found;
+
+							if ( inplace && found != null ) {
+								if ( pass ) {
+									anyFound = true;
+
+								} else {
+									curLoop[i] = false;
+								}
+
+							} else if ( pass ) {
+								result.push( item );
+								anyFound = true;
+							}
+						}
+					}
+				}
+
+				if ( found !== undefined ) {
+					if ( !inplace ) {
+						curLoop = result;
+					}
+
+					expr = expr.replace( Expr.match[ type ], "" );
+
+					if ( !anyFound ) {
+						return [];
+					}
+
+					break;
+				}
+			}
+		}
+
+		// Improper expression
+		if ( expr === old ) {
+			if ( anyFound == null ) {
+				Sizzle.error( expr );
+
+			} else {
+				break;
+			}
+		}
+
+		old = expr;
+	}
+
+	return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+	throw "Syntax error, unrecognized expression: " + msg;
+};
+
+var Expr = Sizzle.selectors = {
+	order: [ "ID", "NAME", "TAG" ],
+
+	match: {
+		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
+		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+	},
+
+	leftMatch: {},
+
+	attrMap: {
+		"class": "className",
+		"for": "htmlFor"
+	},
+
+	attrHandle: {
+		href: function( elem ) {
+			return elem.getAttribute( "href" );
+		},
+		type: function( elem ) {
+			return elem.getAttribute( "type" );
+		}
+	},
+
+	relative: {
+		"+": function(checkSet, part){
+			var isPartStr = typeof part === "string",
+				isTag = isPartStr && !rNonWord.test( part ),
+				isPartStrNotTag = isPartStr && !isTag;
+
+			if ( isTag ) {
+				part = part.toLowerCase();
+			}
+
+			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+				if ( (elem = checkSet[i]) ) {
+					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+						elem || false :
+						elem === part;
+				}
+			}
+
+			if ( isPartStrNotTag ) {
+				Sizzle.filter( part, checkSet, true );
+			}
+		},
+
+		">": function( checkSet, part ) {
+			var elem,
+				isPartStr = typeof part === "string",
+				i = 0,
+				l = checkSet.length;
+
+			if ( isPartStr && !rNonWord.test( part ) ) {
+				part = part.toLowerCase();
+
+				for ( ; i < l; i++ ) {
+					elem = checkSet[i];
+
+					if ( elem ) {
+						var parent = elem.parentNode;
+						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+					}
+				}
+
+			} else {
+				for ( ; i < l; i++ ) {
+					elem = checkSet[i];
+
+					if ( elem ) {
+						checkSet[i] = isPartStr ?
+							elem.parentNode :
+							elem.parentNode === part;
+					}
+				}
+
+				if ( isPartStr ) {
+					Sizzle.filter( part, checkSet, true );
+				}
+			}
+		},
+
+		"": function(checkSet, part, isXML){
+			var nodeCheck,
+				doneName = done++,
+				checkFn = dirCheck;
+
+			if ( typeof part === "string" && !rNonWord.test( part ) ) {
+				part = part.toLowerCase();
+				nodeCheck = part;
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+		},
+
+		"~": function( checkSet, part, isXML ) {
+			var nodeCheck,
+				doneName = done++,
+				checkFn = dirCheck;
+
+			if ( typeof part === "string" && !rNonWord.test( part ) ) {
+				part = part.toLowerCase();
+				nodeCheck = part;
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+		}
+	},
+
+	find: {
+		ID: function( match, context, isXML ) {
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [m] : [];
+			}
+		},
+
+		NAME: function( match, context ) {
+			if ( typeof context.getElementsByName !== "undefined" ) {
+				var ret = [],
+					results = context.getElementsByName( match[1] );
+
+				for ( var i = 0, l = results.length; i < l; i++ ) {
+					if ( results[i].getAttribute("name") === match[1] ) {
+						ret.push( results[i] );
+					}
+				}
+
+				return ret.length === 0 ? null : ret;
+			}
+		},
+
+		TAG: function( match, context ) {
+			if ( typeof context.getElementsByTagName !== "undefined" ) {
+				return context.getElementsByTagName( match[1] );
+			}
+		}
+	},
+	preFilter: {
+		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+			match = " " + match[1].replace( rBackslash, "" ) + " ";
+
+			if ( isXML ) {
+				return match;
+			}
+
+			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+				if ( elem ) {
+					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+						if ( !inplace ) {
+							result.push( elem );
+						}
+
+					} else if ( inplace ) {
+						curLoop[i] = false;
+					}
+				}
+			}
+
+			return false;
+		},
+
+		ID: function( match ) {
+			return match[1].replace( rBackslash, "" );
+		},
+
+		TAG: function( match, curLoop ) {
+			return match[1].replace( rBackslash, "" ).toLowerCase();
+		},
+
+		CHILD: function( match ) {
+			if ( match[1] === "nth" ) {
+				if ( !match[2] ) {
+					Sizzle.error( match[0] );
+				}
+
+				match[2] = match[2].replace(/^\+|\s*/g, '');
+
+				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+				var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+				// calculate the numbers (first)n+(last) including if they are negative
+				match[2] = (test[1] + (test[2] || 1)) - 0;
+				match[3] = test[3] - 0;
+			}
+			else if ( match[2] ) {
+				Sizzle.error( match[0] );
+			}
+
+			// TODO: Move to normal caching system
+			match[0] = done++;
+
+			return match;
+		},
+
+		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+			var name = match[1] = match[1].replace( rBackslash, "" );
+			
+			if ( !isXML && Expr.attrMap[name] ) {
+				match[1] = Expr.attrMap[name];
+			}
+
+			// Handle if an un-quoted value was used
+			match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+
+			if ( match[2] === "~=" ) {
+				match[4] = " " + match[4] + " ";
+			}
+
+			return match;
+		},
+
+		PSEUDO: function( match, curLoop, inplace, result, not ) {
+			if ( match[1] === "not" ) {
+				// If we're dealing with a complex expression, or a simple one
+				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+					match[3] = Sizzle(match[3], null, null, curLoop);
+
+				} else {
+					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+					if ( !inplace ) {
+						result.push.apply( result, ret );
+					}
+
+					return false;
+				}
+
+			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+				return true;
+			}
+			
+			return match;
+		},
+
+		POS: function( match ) {
+			match.unshift( true );
+
+			return match;
+		}
+	},
+	
+	filters: {
+		enabled: function( elem ) {
+			return elem.disabled === false && elem.type !== "hidden";
+		},
+
+		disabled: function( elem ) {
+			return elem.disabled === true;
+		},
+
+		checked: function( elem ) {
+			return elem.checked === true;
+		},
+		
+		selected: function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+			
+			return elem.selected === true;
+		},
+
+		parent: function( elem ) {
+			return !!elem.firstChild;
+		},
+
+		empty: function( elem ) {
+			return !elem.firstChild;
+		},
+
+		has: function( elem, i, match ) {
+			return !!Sizzle( match[3], elem ).length;
+		},
+
+		header: function( elem ) {
+			return (/h\d/i).test( elem.nodeName );
+		},
+
+		text: function( elem ) {
+			var attr = elem.getAttribute( "type" ), type = elem.type;
+			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
+			// use getAttribute instead to test this case
+			return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+		},
+
+		radio: function( elem ) {
+			return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+		},
+
+		checkbox: function( elem ) {
+			return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+		},
+
+		file: function( elem ) {
+			return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+		},
+
+		password: function( elem ) {
+			return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+		},
+
+		submit: function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return (name === "input" || name === "button") && "submit" === elem.type;
+		},
+
+		image: function( elem ) {
+			return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+		},
+
+		reset: function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return (name === "input" || name === "button") && "reset" === elem.type;
+		},
+
+		button: function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && "button" === elem.type || name === "button";
+		},
+
+		input: function( elem ) {
+			return (/input|select|textarea|button/i).test( elem.nodeName );
+		},
+
+		focus: function( elem ) {
+			return elem === elem.ownerDocument.activeElement;
+		}
+	},
+	setFilters: {
+		first: function( elem, i ) {
+			return i === 0;
+		},
+
+		last: function( elem, i, match, array ) {
+			return i === array.length - 1;
+		},
+
+		even: function( elem, i ) {
+			return i % 2 === 0;
+		},
+
+		odd: function( elem, i ) {
+			return i % 2 === 1;
+		},
+
+		lt: function( elem, i, match ) {
+			return i < match[3] - 0;
+		},
+
+		gt: function( elem, i, match ) {
+			return i > match[3] - 0;
+		},
+
+		nth: function( elem, i, match ) {
+			return match[3] - 0 === i;
+		},
+
+		eq: function( elem, i, match ) {
+			return match[3] - 0 === i;
+		}
+	},
+	filter: {
+		PSEUDO: function( elem, match, i, array ) {
+			var name = match[1],
+				filter = Expr.filters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+
+			} else if ( name === "contains" ) {
+				return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+			} else if ( name === "not" ) {
+				var not = match[3];
+
+				for ( var j = 0, l = not.length; j < l; j++ ) {
+					if ( not[j] === elem ) {
+						return false;
+					}
+				}
+
+				return true;
+
+			} else {
+				Sizzle.error( name );
+			}
+		},
+
+		CHILD: function( elem, match ) {
+			var type = match[1],
+				node = elem;
+
+			switch ( type ) {
+				case "only":
+				case "first":
+					while ( (node = node.previousSibling) )	 {
+						if ( node.nodeType === 1 ) { 
+							return false; 
+						}
+					}
+
+					if ( type === "first" ) { 
+						return true; 
+					}
+
+					node = elem;
+
+				case "last":
+					while ( (node = node.nextSibling) )	 {
+						if ( node.nodeType === 1 ) { 
+							return false; 
+						}
+					}
+
+					return true;
+
+				case "nth":
+					var first = match[2],
+						last = match[3];
+
+					if ( first === 1 && last === 0 ) {
+						return true;
+					}
+					
+					var doneName = match[0],
+						parent = elem.parentNode;
+	
+					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+						var count = 0;
+						
+						for ( node = parent.firstChild; node; node = node.nextSibling ) {
+							if ( node.nodeType === 1 ) {
+								node.nodeIndex = ++count;
+							}
+						} 
+
+						parent.sizcache = doneName;
+					}
+					
+					var diff = elem.nodeIndex - last;
+
+					if ( first === 0 ) {
+						return diff === 0;
+
+					} else {
+						return ( diff % first === 0 && diff / first >= 0 );
+					}
+			}
+		},
+
+		ID: function( elem, match ) {
+			return elem.nodeType === 1 && elem.getAttribute("id") === match;
+		},
+
+		TAG: function( elem, match ) {
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
+		},
+		
+		CLASS: function( elem, match ) {
+			return (" " + (elem.className || elem.getAttribute("class")) + " ")
+				.indexOf( match ) > -1;
+		},
+
+		ATTR: function( elem, match ) {
+			var name = match[1],
+				result = Expr.attrHandle[ name ] ?
+					Expr.attrHandle[ name ]( elem ) :
+					elem[ name ] != null ?
+						elem[ name ] :
+						elem.getAttribute( name ),
+				value = result + "",
+				type = match[2],
+				check = match[4];
+
+			return result == null ?
+				type === "!=" :
+				type === "=" ?
+				value === check :
+				type === "*=" ?
+				value.indexOf(check) >= 0 :
+				type === "~=" ?
+				(" " + value + " ").indexOf(check) >= 0 :
+				!check ?
+				value && result !== false :
+				type === "!=" ?
+				value !== check :
+				type === "^=" ?
+				value.indexOf(check) === 0 :
+				type === "$=" ?
+				value.substr(value.length - check.length) === check :
+				type === "|=" ?
+				value === check || value.substr(0, check.length + 1) === check + "-" :
+				false;
+		},
+
+		POS: function( elem, match, i, array ) {
+			var name = match[2],
+				filter = Expr.setFilters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			}
+		}
+	}
+};
+
+var origPOS = Expr.match.POS,
+	fescape = function(all, num){
+		return "\\" + (num - 0 + 1);
+	};
+
+for ( var type in Expr.match ) {
+	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+	array = Array.prototype.slice.call( array, 0 );
+
+	if ( results ) {
+		results.push.apply( results, array );
+		return results;
+	}
+	
+	return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+	makeArray = function( array, results ) {
+		var i = 0,
+			ret = results || [];
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+
+		} else {
+			if ( typeof array.length === "number" ) {
+				for ( var l = array.length; i < l; i++ ) {
+					ret.push( array[i] );
+				}
+
+			} else {
+				for ( ; array[i]; i++ ) {
+					ret.push( array[i] );
+				}
+			}
+		}
+
+		return ret;
+	};
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+			return a.compareDocumentPosition ? -1 : 1;
+		}
+
+		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+	};
+
+} else {
+	sortOrder = function( a, b ) {
+		// The nodes are identical, we can exit early
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+
+		// Fallback to using sourceIndex (in IE) if it's available on both nodes
+		} else if ( a.sourceIndex && b.sourceIndex ) {
+			return a.sourceIndex - b.sourceIndex;
+		}
+
+		var al, bl,
+			ap = [],
+			bp = [],
+			aup = a.parentNode,
+			bup = b.parentNode,
+			cur = aup;
+
+		// If the nodes are siblings (or identical) we can do a quick check
+		if ( aup === bup ) {
+			return siblingCheck( a, b );
+
+		// If no parents were found then the nodes are disconnected
+		} else if ( !aup ) {
+			return -1;
+
+		} else if ( !bup ) {
+			return 1;
+		}
+
+		// Otherwise they're somewhere else in the tree so we need
+		// to build up a full list of the parentNodes for comparison
+		while ( cur ) {
+			ap.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		cur = bup;
+
+		while ( cur ) {
+			bp.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		al = ap.length;
+		bl = bp.length;
+
+		// Start walking down the tree looking for a discrepancy
+		for ( var i = 0; i < al && i < bl; i++ ) {
+			if ( ap[i] !== bp[i] ) {
+				return siblingCheck( ap[i], bp[i] );
+			}
+		}
+
+		// We ended someplace up the tree so do a sibling check
+		return i === al ?
+			siblingCheck( a, bp[i], -1 ) :
+			siblingCheck( ap[i], b, 1 );
+	};
+
+	siblingCheck = function( a, b, ret ) {
+		if ( a === b ) {
+			return ret;
+		}
+
+		var cur = a.nextSibling;
+
+		while ( cur ) {
+			if ( cur === b ) {
+				return -1;
+			}
+
+			cur = cur.nextSibling;
+		}
+
+		return 1;
+	};
+}
+
+// Utility function for retreiving the text value of an array of DOM nodes
+Sizzle.getText = function( elems ) {
+	var ret = "", elem;
+
+	for ( var i = 0; elems[i]; i++ ) {
+		elem = elems[i];
+
+		// Get the text from text nodes and CDATA nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+			ret += elem.nodeValue;
+
+		// Traverse everything else, except comment nodes
+		} else if ( elem.nodeType !== 8 ) {
+			ret += Sizzle.getText( elem.childNodes );
+		}
+	}
+
+	return ret;
+};
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+	// We're going to inject a fake input element with a specified name
+	var form = document.createElement("div"),
+		id = "script" + (new Date()).getTime(),
+		root = document.documentElement;
+
+	form.innerHTML = "<a name='" + id + "'/>";
+
+	// Inject it into the root element, check its status, and remove it quickly
+	root.insertBefore( form, root.firstChild );
+
+	// The workaround has to do additional checks after a getElementById
+	// Which slows things down for other browsers (hence the branching)
+	if ( document.getElementById( id ) ) {
+		Expr.find.ID = function( match, context, isXML ) {
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+
+				return m ?
+					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+						[m] :
+						undefined :
+					[];
+			}
+		};
+
+		Expr.filter.ID = function( elem, match ) {
+			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+			return elem.nodeType === 1 && node && node.nodeValue === match;
+		};
+	}
+
+	root.removeChild( form );
+
+	// release memory in IE
+	root = form = null;
+})();
+
+(function(){
+	// Check to see if the browser returns only elements
+	// when doing getElementsByTagName("*")
+
+	// Create a fake element
+	var div = document.createElement("div");
+	div.appendChild( document.createComment("") );
+
+	// Make sure no comments are found
+	if ( div.getElementsByTagName("*").length > 0 ) {
+		Expr.find.TAG = function( match, context ) {
+			var results = context.getElementsByTagName( match[1] );
+
+			// Filter out possible comments
+			if ( match[1] === "*" ) {
+				var tmp = [];
+
+				for ( var i = 0; results[i]; i++ ) {
+					if ( results[i].nodeType === 1 ) {
+						tmp.push( results[i] );
+					}
+				}
+
+				results = tmp;
+			}
+
+			return results;
+		};
+	}
+
+	// Check to see if an attribute returns normalized href attributes
+	div.innerHTML = "<a href='#'></a>";
+
+	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+			div.firstChild.getAttribute("href") !== "#" ) {
+
+		Expr.attrHandle.href = function( elem ) {
+			return elem.getAttribute( "href", 2 );
+		};
+	}
+
+	// release memory in IE
+	div = null;
+})();
+
+if ( document.querySelectorAll ) {
+	(function(){
+		var oldSizzle = Sizzle,
+			div = document.createElement("div"),
+			id = "__sizzle__";
+
+		div.innerHTML = "<p class='TEST'></p>";
+
+		// Safari can't handle uppercase or unicode characters when
+		// in quirks mode.
+		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+			return;
+		}
+	
+		Sizzle = function( query, context, extra, seed ) {
+			context = context || document;
+
+			// Only use querySelectorAll on non-XML documents
+			// (ID selectors don't work in non-HTML documents)
+			if ( !seed && !Sizzle.isXML(context) ) {
+				// See if we find a selector to speed up
+				var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
+				
+				if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+					// Speed-up: Sizzle("TAG")
+					if ( match[1] ) {
+						return makeArray( context.getElementsByTagName( query ), extra );
+					
+					// Speed-up: Sizzle(".CLASS")
+					} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+						return makeArray( context.getElementsByClassName( match[2] ), extra );
+					}
+				}
+				
+				if ( context.nodeType === 9 ) {
+					// Speed-up: Sizzle("body")
+					// The body element only exists once, optimize finding it
+					if ( query === "body" && context.body ) {
+						return makeArray( [ context.body ], extra );
+						
+					// Speed-up: Sizzle("#ID")
+					} else if ( match && match[3] ) {
+						var elem = context.getElementById( match[3] );
+
+						// Check parentNode to catch when Blackberry 4.6 returns
+						// nodes that are no longer in the document #6963
+						if ( elem && elem.parentNode ) {
+							// Handle the case where IE and Opera return items
+							// by name instead of ID
+							if ( elem.id === match[3] ) {
+								return makeArray( [ elem ], extra );
+							}
+							
+						} else {
+							return makeArray( [], extra );
+						}
+					}
+					
+					try {
+						return makeArray( context.querySelectorAll(query), extra );
+					} catch(qsaError) {}
+
+				// qSA works strangely on Element-rooted queries
+				// We can work around this by specifying an extra ID on the root
+				// and working up from there (Thanks to Andrew Dupont for the technique)
+				// IE 8 doesn't work on object elements
+				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+					var oldContext = context,
+						old = context.getAttribute( "id" ),
+						nid = old || id,
+						hasParent = context.parentNode,
+						relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+					if ( !old ) {
+						context.setAttribute( "id", nid );
+					} else {
+						nid = nid.replace( /'/g, "\\$&" );
+					}
+					if ( relativeHierarchySelector && hasParent ) {
+						context = context.parentNode;
+					}
+
+					try {
+						if ( !relativeHierarchySelector || hasParent ) {
+							return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+						}
+
+					} catch(pseudoError) {
+					} finally {
+						if ( !old ) {
+							oldContext.removeAttribute( "id" );
+						}
+					}
+				}
+			}
+		
+			return oldSizzle(query, context, extra, seed);
+		};
+
+		for ( var prop in oldSizzle ) {
+			Sizzle[ prop ] = oldSizzle[ prop ];
+		}
+
+		// release memory in IE
+		div = null;
+	})();
+}
+
+(function(){
+	var html = document.documentElement,
+		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
+
+	if ( matches ) {
+		// Check to see if it's possible to do matchesSelector
+		// on a disconnected node (IE 9 fails this)
+		var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+			pseudoWorks = false;
+
+		try {
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( document.documentElement, "[test!='']:sizzle" );
+	
+		} catch( pseudoError ) {
+			pseudoWorks = true;
+		}
+
+		Sizzle.matchesSelector = function( node, expr ) {
+			// Make sure that attribute selectors are quoted
+			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+			if ( !Sizzle.isXML( node ) ) {
+				try { 
+					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+						var ret = matches.call( node, expr );
+
+						// IE 9's matchesSelector returns false on disconnected nodes
+						if ( ret || !disconnectedMatch ||
+								// As well, disconnected nodes are said to be in a document
+								// fragment in IE 9, so check for that
+								node.document && node.document.nodeType !== 11 ) {
+							return ret;
+						}
+					}
+				} catch(e) {}
+			}
+
+			return Sizzle(expr, null, null, [node]).length > 0;
+		};
+	}
+})();
+
+(function(){
+	var div = document.createElement("div");
+
+	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+	// Opera can't find a second classname (in 9.6)
+	// Also, make sure that getElementsByClassName actually exists
+	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+		return;
+	}
+
+	// Safari caches class attributes, doesn't catch changes (in 3.2)
+	div.lastChild.className = "e";
+
+	if ( div.getElementsByClassName("e").length === 1 ) {
+		return;
+	}
+	
+	Expr.order.splice(1, 0, "CLASS");
+	Expr.find.CLASS = function( match, context, isXML ) {
+		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+			return context.getElementsByClassName(match[1]);
+		}
+	};
+
+	// release memory in IE
+	div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+
+		if ( elem ) {
+			var match = false;
+
+			elem = elem[dir];
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 && !isXML ){
+					elem.sizcache = doneName;
+					elem.sizset = i;
+				}
+
+				if ( elem.nodeName.toLowerCase() === cur ) {
+					match = elem;
+					break;
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+
+		if ( elem ) {
+			var match = false;
+			
+			elem = elem[dir];
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 ) {
+					if ( !isXML ) {
+						elem.sizcache = doneName;
+						elem.sizset = i;
+					}
+
+					if ( typeof cur !== "string" ) {
+						if ( elem === cur ) {
+							match = true;
+							break;
+						}
+
+					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+						match = elem;
+						break;
+					}
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+if ( document.documentElement.contains ) {
+	Sizzle.contains = function( a, b ) {
+		return a !== b && (a.contains ? a.contains(b) : true);
+	};
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+	Sizzle.contains = function( a, b ) {
+		return !!(a.compareDocumentPosition(b) & 16);
+	};
+
+} else {
+	Sizzle.contains = function() {
+		return false;
+	};
+}
+
+Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833) 
+	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context ) {
+	var match,
+		tmpSet = [],
+		later = "",
+		root = context.nodeType ? [context] : context;
+
+	// Position selectors must be done after the filter
+	// And so must :not(positional) so we move all PSEUDOs to the end
+	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+		later += match[0];
+		selector = selector.replace( Expr.match.PSEUDO, "" );
+	}
+
+	selector = Expr.relative[selector] ? selector + "*" : selector;
+
+	for ( var i = 0, l = root.length; i < l; i++ ) {
+		Sizzle( selector, root[i], tmpSet );
+	}
+
+	return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+	// Note: This RegExp should be improved, or likely pulled from Sizzle
+	rmultiselector = /,/,
+	isSimple = /^.[^:#\[\.,]*$/,
+	slice = Array.prototype.slice,
+	POS = jQuery.expr.match.POS,
+	// methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var self = this,
+			i, l;
+
+		if ( typeof selector !== "string" ) {
+			return jQuery( selector ).filter(function() {
+				for ( i = 0, l = self.length; i < l; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			});
+		}
+
+		var ret = this.pushStack( "", "find", selector ),
+			length, n, r;
+
+		for ( i = 0, l = this.length; i < l; i++ ) {
+			length = ret.length;
+			jQuery.find( selector, this[i], ret );
+
+			if ( i > 0 ) {
+				// Make sure that the results are unique
+				for ( n = length; n < ret.length; n++ ) {
+					for ( r = 0; r < length; r++ ) {
+						if ( ret[r] === ret[n] ) {
+							ret.splice(n--, 1);
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		return ret;
+	},
+
+	has: function( target ) {
+		var targets = jQuery( target );
+		return this.filter(function() {
+			for ( var i = 0, l = targets.length; i < l; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector, false), "not", selector);
+	},
+
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector, true), "filter", selector );
+	},
+
+	is: function( selector ) {
+		return !!selector && ( typeof selector === "string" ?
+			jQuery.filter( selector, this ).length > 0 :
+			this.filter( selector ).length > 0 );
+	},
+
+	closest: function( selectors, context ) {
+		var ret = [], i, l, cur = this[0];
+		
+		// Array
+		if ( jQuery.isArray( selectors ) ) {
+			var match, selector,
+				matches = {},
+				level = 1;
+
+			if ( cur && selectors.length ) {
+				for ( i = 0, l = selectors.length; i < l; i++ ) {
+					selector = selectors[i];
+
+					if ( !matches[ selector ] ) {
+						matches[ selector ] = POS.test( selector ) ?
+							jQuery( selector, context || this.context ) :
+							selector;
+					}
+				}
+
+				while ( cur && cur.ownerDocument && cur !== context ) {
+					for ( selector in matches ) {
+						match = matches[ selector ];
+
+						if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {
+							ret.push({ selector: selector, elem: cur, level: level });
+						}
+					}
+
+					cur = cur.parentNode;
+					level++;
+				}
+			}
+
+			return ret;
+		}
+
+		// String
+		var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( i = 0, l = this.length; i < l; i++ ) {
+			cur = this[i];
+
+			while ( cur ) {
+				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+					ret.push( cur );
+					break;
+
+				} else {
+					cur = cur.parentNode;
+					if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+						break;
+					}
+				}
+			}
+		}
+
+		ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+		return this.pushStack( ret, "closest", selectors );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+		if ( !elem || typeof elem === "string" ) {
+			return jQuery.inArray( this[0],
+				// If it receives a string, the selector is used
+				// If it receives nothing, the siblings are used
+				elem ? jQuery( elem ) : this.parent().children() );
+		}
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		var set = typeof selector === "string" ?
+				jQuery( selector, context ) :
+				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+			all = jQuery.merge( this.get(), set );
+
+		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+			all :
+			jQuery.unique( all ) );
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	}
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+	return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return jQuery.nth( elem, 2, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return jQuery.nth( elem, 2, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( elem.parentNode.firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.makeArray( elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until ),
+			// The variable 'args' was introduced in
+			// https://github.com/jquery/jquery/commit/52a0238
+			// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
+			// http://code.google.com/p/v8/issues/detail?id=1050
+			args = slice.call(arguments);
+
+		if ( !runtil.test( name ) ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+			ret = ret.reverse();
+		}
+
+		return this.pushStack( ret, name, args.join(",") );
+	};
+});
+
+jQuery.extend({
+	filter: function( expr, elems, not ) {
+		if ( not ) {
+			expr = ":not(" + expr + ")";
+		}
+
+		return elems.length === 1 ?
+			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+			jQuery.find.matches(expr, elems);
+	},
+
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	nth: function( cur, result, dir, elem ) {
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] ) {
+			if ( cur.nodeType === 1 && ++num === result ) {
+				break;
+			}
+		}
+
+		return cur;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+	// Can't pass null or undefined to indexOf in Firefox 4
+	// Set to 0 to skip string check
+	qualifier = qualifier || 0;
+
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			var retVal = !!qualifier.call( elem, i, elem );
+			return retVal === keep;
+		});
+
+	} else if ( qualifier.nodeType ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			return (elem === qualifier) === keep;
+		});
+
+	} else if ( typeof qualifier === "string" ) {
+		var filtered = jQuery.grep(elements, function( elem ) {
+			return elem.nodeType === 1;
+		});
+
+		if ( isSimple.test( qualifier ) ) {
+			return jQuery.filter(qualifier, filtered, !keep);
+		} else {
+			qualifier = jQuery.filter( qualifier, filtered );
+		}
+	}
+
+	return jQuery.grep(elements, function( elem, i ) {
+		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+	});
+}
+
+
+
+
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnocache = /<(?:script|object|embed|option|style)/i,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /\/(java|ecma)script/i,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		area: [ 1, "<map>", "</map>" ],
+		_default: [ 0, "", "" ]
+	};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+	wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+	text: function( text ) {
+		if ( jQuery.isFunction(text) ) {
+			return this.each(function(i) {
+				var self = jQuery( this );
+
+				self.text( text.call(this, i, self.text()) );
+			});
+		}
+
+		if ( typeof text !== "object" && text !== undefined ) {
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+		}
+
+		return jQuery.text( this );
+	},
+
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function() {
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 ) {
+				this.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 ) {
+				this.insertBefore( elem, this.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		if ( this[0] && this[0].parentNode ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this );
+			});
+		} else if ( arguments.length ) {
+			var set = jQuery(arguments[0]);
+			set.push.apply( set, this.toArray() );
+			return this.pushStack( set, "before", arguments );
+		}
+	},
+
+	after: function() {
+		if ( this[0] && this[0].parentNode ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			});
+		} else if ( arguments.length ) {
+			var set = this.pushStack( this, "after", arguments );
+			set.push.apply( set, jQuery(arguments[0]).toArray() );
+			return set;
+		}
+	},
+
+	// keepData is for internal use only--do not document
+	remove: function( selector, keepData ) {
+		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+				if ( !keepData && elem.nodeType === 1 ) {
+					jQuery.cleanData( elem.getElementsByTagName("*") );
+					jQuery.cleanData( [ elem ] );
+				}
+
+				if ( elem.parentNode ) {
+					elem.parentNode.removeChild( elem );
+				}
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( elem.getElementsByTagName("*") );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map( function () {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		if ( value === undefined ) {
+			return this[0] && this[0].nodeType === 1 ?
+				this[0].innerHTML.replace(rinlinejQuery, "") :
+				null;
+
+		// See if we can take a shortcut and just use innerHTML
+		} else if ( typeof value === "string" && !rnocache.test( value ) &&
+			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+			value = value.replace(rxhtmlTag, "<$1></$2>");
+
+			try {
+				for ( var i = 0, l = this.length; i < l; i++ ) {
+					// Remove element nodes and prevent memory leaks
+					if ( this[i].nodeType === 1 ) {
+						jQuery.cleanData( this[i].getElementsByTagName("*") );
+						this[i].innerHTML = value;
+					}
+				}
+
+			// If using innerHTML throws an exception, use the fallback method
+			} catch(e) {
+				this.empty().append( value );
+			}
+
+		} else if ( jQuery.isFunction( value ) ) {
+			this.each(function(i){
+				var self = jQuery( this );
+
+				self.html( value.call(this, i, self.html()) );
+			});
+
+		} else {
+			this.empty().append( value );
+		}
+
+		return this;
+	},
+
+	replaceWith: function( value ) {
+		if ( this[0] && this[0].parentNode ) {
+			// Make sure that the elements are removed from the DOM before they are inserted
+			// this can help fix replacing a parent with child elements
+			if ( jQuery.isFunction( value ) ) {
+				return this.each(function(i) {
+					var self = jQuery(this), old = self.html();
+					self.replaceWith( value.call( this, i, old ) );
+				});
+			}
+
+			if ( typeof value !== "string" ) {
+				value = jQuery( value ).detach();
+			}
+
+			return this.each(function() {
+				var next = this.nextSibling,
+					parent = this.parentNode;
+
+				jQuery( this ).remove();
+
+				if ( next ) {
+					jQuery(next).before( value );
+				} else {
+					jQuery(parent).append( value );
+				}
+			});
+		} else {
+			return this.length ?
+				this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+				this;
+		}
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, table, callback ) {
+		var results, first, fragment, parent,
+			value = args[0],
+			scripts = [];
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+			return this.each(function() {
+				jQuery(this).domManip( args, table, callback, true );
+			});
+		}
+
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				args[0] = value.call(this, i, table ? self.html() : undefined);
+				self.domManip( args, table, callback );
+			});
+		}
+
+		if ( this[0] ) {
+			parent = value && value.parentNode;
+
+			// If we're in a fragment, just use that instead of building a new one
+			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+				results = { fragment: parent };
+
+			} else {
+				results = jQuery.buildFragment( args, this, scripts );
+			}
+
+			fragment = results.fragment;
+
+			if ( fragment.childNodes.length === 1 ) {
+				first = fragment = fragment.firstChild;
+			} else {
+				first = fragment.firstChild;
+			}
+
+			if ( first ) {
+				table = table && jQuery.nodeName( first, "tr" );
+
+				for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+					callback.call(
+						table ?
+							root(this[i], first) :
+							this[i],
+						// Make sure that we do not leak memory by inadvertently discarding
+						// the original fragment (which might have attached data) instead of
+						// using it; in addition, use the original fragment object for the last
+						// item instead of first because it can end up being emptied incorrectly
+						// in certain situations (Bug #8070).
+						// Fragments from the fragment cache must always be cloned and never used
+						// in place.
+						results.cacheable || (l > 1 && i < lastIndex) ?
+							jQuery.clone( fragment, true, true ) :
+							fragment
+					);
+				}
+			}
+
+			if ( scripts.length ) {
+				jQuery.each( scripts, evalScript );
+			}
+		}
+
+		return this;
+	}
+});
+
+function root( elem, cur ) {
+	return jQuery.nodeName(elem, "table") ?
+		(elem.getElementsByTagName("tbody")[0] ||
+		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+		elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+
+	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+		return;
+	}
+
+	var internalKey = jQuery.expando,
+		oldData = jQuery.data( src ),
+		curData = jQuery.data( dest, oldData );
+
+	// Switch to use the internal data object, if it exists, for the next
+	// stage of data copying
+	if ( (oldData = oldData[ internalKey ]) ) {
+		var events = oldData.events;
+				curData = curData[ internalKey ] = jQuery.extend({}, oldData);
+
+		if ( events ) {
+			delete curData.handle;
+			curData.events = {};
+
+			for ( var type in events ) {
+				for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
+					jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
+				}
+			}
+		}
+	}
+}
+
+function cloneFixAttributes( src, dest ) {
+	var nodeName;
+
+	// We do not need to do anything for non-Elements
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	// clearAttributes removes the attributes, which we don't want,
+	// but also removes the attachEvent events, which we *do* want
+	if ( dest.clearAttributes ) {
+		dest.clearAttributes();
+	}
+
+	// mergeAttributes, in contrast, only merges back on the
+	// original attributes, not the events
+	if ( dest.mergeAttributes ) {
+		dest.mergeAttributes( src );
+	}
+
+	nodeName = dest.nodeName.toLowerCase();
+
+	// IE6-8 fail to clone children inside object elements that use
+	// the proprietary classid attribute value (rather than the type
+	// attribute) to identify the type of content to display
+	if ( nodeName === "object" ) {
+		dest.outerHTML = src.outerHTML;
+
+	} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+		// IE6-8 fails to persist the checked state of a cloned checkbox
+		// or radio button. Worse, IE6-7 fail to give the cloned element
+		// a checked appearance if the defaultChecked value isn't also set
+		if ( src.checked ) {
+			dest.defaultChecked = dest.checked = src.checked;
+		}
+
+		// IE6-7 get confused and end up setting the value of a cloned
+		// checkbox/radio button to an empty string instead of "on"
+		if ( dest.value !== src.value ) {
+			dest.value = src.value;
+		}
+
+	// IE6-8 fails to return the selected option to the default selected
+	// state when cloning options
+	} else if ( nodeName === "option" ) {
+		dest.selected = src.defaultSelected;
+
+	// IE6-8 fails to set the defaultValue to the correct value when
+	// cloning other types of input fields
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+
+	// Event data gets referenced instead of copied if the expando
+	// gets copied too
+	dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+	var fragment, cacheable, cacheresults, doc;
+
+  // nodes may contain either an explicit document object,
+  // a jQuery collection or context object.
+  // If nodes[0] contains a valid object to assign to doc
+  if ( nodes && nodes[0] ) {
+    doc = nodes[0].ownerDocument || nodes[0];
+  }
+
+  // Ensure that an attr object doesn't incorrectly stand in as a document object
+	// Chrome and Firefox seem to allow this to occur and will throw exception
+	// Fixes #8950
+	if ( !doc.createDocumentFragment ) {
+		doc = document;
+	}
+
+	// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+	// Cloning options loses the selected state, so don't cache them
+	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
+		args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+
+		cacheable = true;
+
+		cacheresults = jQuery.fragments[ args[0] ];
+		if ( cacheresults && cacheresults !== 1 ) {
+			fragment = cacheresults;
+		}
+	}
+
+	if ( !fragment ) {
+		fragment = doc.createDocumentFragment();
+		jQuery.clean( args, doc, fragment, scripts );
+	}
+
+	if ( cacheable ) {
+		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
+	}
+
+	return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = [],
+			insert = jQuery( selector ),
+			parent = this.length === 1 && this[0].parentNode;
+
+		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+			insert[ original ]( this[0] );
+			return this;
+
+		} else {
+			for ( var i = 0, l = insert.length; i < l; i++ ) {
+				var elems = (i > 0 ? this.clone(true) : this).get();
+				jQuery( insert[i] )[ original ]( elems );
+				ret = ret.concat( elems );
+			}
+
+			return this.pushStack( ret, name, insert.selector );
+		}
+	};
+});
+
+function getAll( elem ) {
+	if ( "getElementsByTagName" in elem ) {
+		return elem.getElementsByTagName( "*" );
+
+	} else if ( "querySelectorAll" in elem ) {
+		return elem.querySelectorAll( "*" );
+
+	} else {
+		return [];
+	}
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+	if ( elem.type === "checkbox" || elem.type === "radio" ) {
+		elem.defaultChecked = elem.checked;
+	}
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+	if ( jQuery.nodeName( elem, "input" ) ) {
+		fixDefaultChecked( elem );
+	} else if ( "getElementsByTagName" in elem ) {
+		jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var clone = elem.cloneNode(true),
+				srcElements,
+				destElements,
+				i;
+
+		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+			// IE copies events bound via attachEvent when using cloneNode.
+			// Calling detachEvent on the clone will also remove the events
+			// from the original. In order to get around this, we use some
+			// proprietary methods to clear the events. Thanks to MooTools
+			// guys for this hotness.
+
+			cloneFixAttributes( elem, clone );
+
+			// Using Sizzle here is crazy slow, so we use getElementsByTagName
+			// instead
+			srcElements = getAll( elem );
+			destElements = getAll( clone );
+
+			// Weird iteration because IE will replace the length property
+			// with an element if you are cloning the body and one of the
+			// elements on the page has a name or id of "length"
+			for ( i = 0; srcElements[i]; ++i ) {
+				cloneFixAttributes( srcElements[i], destElements[i] );
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			cloneCopyEvent( elem, clone );
+
+			if ( deepDataAndEvents ) {
+				srcElements = getAll( elem );
+				destElements = getAll( clone );
+
+				for ( i = 0; srcElements[i]; ++i ) {
+					cloneCopyEvent( srcElements[i], destElements[i] );
+				}
+			}
+		}
+
+		srcElements = destElements = null;
+
+		// Return the cloned set
+		return clone;
+	},
+
+	clean: function( elems, context, fragment, scripts ) {
+		var checkScriptType;
+
+		context = context || document;
+
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if ( typeof context.createElement === "undefined" ) {
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+		}
+
+		var ret = [], j;
+
+		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+			if ( typeof elem === "number" ) {
+				elem += "";
+			}
+
+			if ( !elem ) {
+				continue;
+			}
+
+			// Convert html string into DOM nodes
+			if ( typeof elem === "string" ) {
+				if ( !rhtml.test( elem ) ) {
+					elem = context.createTextNode( elem );
+				} else {
+					// Fix "XHTML"-style tags in all browsers
+					elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+					// Trim whitespace, otherwise indexOf won't work as expected
+					var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+						wrap = wrapMap[ tag ] || wrapMap._default,
+						depth = wrap[0],
+						div = context.createElement("div");
+
+					// Go to html and back, then peel off extra wrappers
+					div.innerHTML = wrap[1] + elem + wrap[2];
+
+					// Move to the right depth
+					while ( depth-- ) {
+						div = div.lastChild;
+					}
+
+					// Remove IE's autoinserted <tbody> from table fragments
+					if ( !jQuery.support.tbody ) {
+
+						// String was a <table>, *may* have spurious <tbody>
+						var hasBody = rtbody.test(elem),
+							tbody = tag === "table" && !hasBody ?
+								div.firstChild && div.firstChild.childNodes :
+
+								// String was a bare <thead> or <tfoot>
+								wrap[1] === "<table>" && !hasBody ?
+									div.childNodes :
+									[];
+
+						for ( j = tbody.length - 1; j >= 0 ; --j ) {
+							if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+								tbody[ j ].parentNode.removeChild( tbody[ j ] );
+							}
+						}
+					}
+
+					// IE completely kills leading whitespace when innerHTML is used
+					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+						div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+					}
+
+					elem = div.childNodes;
+				}
+			}
+
+			// Resets defaultChecked for any radios and checkboxes
+			// about to be appended to the DOM in IE 6/7 (#8060)
+			var len;
+			if ( !jQuery.support.appendChecked ) {
+				if ( elem[0] && typeof (len = elem.length) === "number" ) {
+					for ( j = 0; j < len; j++ ) {
+						findInputs( elem[j] );
+					}
+				} else {
+					findInputs( elem );
+				}
+			}
+
+			if ( elem.nodeType ) {
+				ret.push( elem );
+			} else {
+				ret = jQuery.merge( ret, elem );
+			}
+		}
+
+		if ( fragment ) {
+			checkScriptType = function( elem ) {
+				return !elem.type || rscriptType.test( elem.type );
+			};
+			for ( i = 0; ret[i]; i++ ) {
+				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+				} else {
+					if ( ret[i].nodeType === 1 ) {
+						var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
+
+						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+					}
+					fragment.appendChild( ret[i] );
+				}
+			}
+		}
+
+		return ret;
+	},
+
+	cleanData: function( elems ) {
+		var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
+			deleteExpando = jQuery.support.deleteExpando;
+
+		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+				continue;
+			}
+
+			id = elem[ jQuery.expando ];
+
+			if ( id ) {
+				data = cache[ id ] && cache[ id ][ internalKey ];
+
+				if ( data && data.events ) {
+					for ( var type in data.events ) {
+						if ( special[ type ] ) {
+							jQuery.event.remove( elem, type );
+
+						// This is a shortcut to avoid jQuery.event.remove's overhead
+						} else {
+							jQuery.removeEvent( elem, type, data.handle );
+						}
+					}
+
+					// Null the DOM reference to avoid IE6/7/8 leak (#7054)
+					if ( data.handle ) {
+						data.handle.elem = null;
+					}
+				}
+
+				if ( deleteExpando ) {
+					delete elem[ jQuery.expando ];
+
+				} else if ( elem.removeAttribute ) {
+					elem.removeAttribute( jQuery.expando );
+				}
+
+				delete cache[ id ];
+			}
+		}
+	}
+});
+
+function evalScript( i, elem ) {
+	if ( elem.src ) {
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+	} else {
+		jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+	}
+
+	if ( elem.parentNode ) {
+		elem.parentNode.removeChild( elem );
+	}
+}
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity=([^)]*)/,
+	// fixed for IE9, see #8346
+	rupper = /([A-Z]|^ms)/g,
+	rnumpx = /^-?\d+(?:px)?$/i,
+	rnum = /^-?\d/,
+	rrelNum = /^[+\-]=/,
+	rrelNumFilter = /[^+\-\.\de]+/g,
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssWidth = [ "Left", "Right" ],
+	cssHeight = [ "Top", "Bottom" ],
+	curCSS,
+
+	getComputedStyle,
+	currentStyle;
+
+jQuery.fn.css = function( name, value ) {
+	// Setting 'undefined' is a no-op
+	if ( arguments.length === 2 && value === undefined ) {
+		return this;
+	}
+
+	return jQuery.access( this, name, value, true, function( elem, name, value ) {
+		return value !== undefined ?
+			jQuery.style( elem, name, value ) :
+			jQuery.css( elem, name );
+	});
+};
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity", "opacity" );
+					return ret === "" ? "1" : ret;
+
+				} else {
+					return elem.style.opacity;
+				}
+			}
+		}
+	},
+
+	// Exclude the following css properties to add px
+	cssNumber: {
+		"fillOpacity": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, origName = jQuery.camelCase( name ),
+			style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+		name = jQuery.cssProps[ origName ] || origName;
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// Make sure that NaN and null values aren't set. See: #7116
+			if ( type === "number" && isNaN( value ) || value == null ) {
+				return;
+			}
+
+			// convert relative number strings (+= or -=) to relative numbers. #7345
+			if ( type === "string" && rrelNum.test( value ) ) {
+				value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+				// Fixes bug #5509
+				try {
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra ) {
+		var ret, hooks;
+
+		// Make sure that we're working with the right name
+		name = jQuery.camelCase( name );
+		hooks = jQuery.cssHooks[ name ];
+		name = jQuery.cssProps[ name ] || name;
+
+		// cssFloat needs a special treatment
+		if ( name === "cssFloat" ) {
+			name = "float";
+		}
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+			return ret;
+
+		// Otherwise, if a way to get the computed value exists, use that
+		} else if ( curCSS ) {
+			return curCSS( elem, name );
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( name in options ) {
+			elem.style[ name ] = old[ name ];
+		}
+	}
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			var val;
+
+			if ( computed ) {
+				if ( elem.offsetWidth !== 0 ) {
+					return getWH( elem, name, extra );
+				} else {
+					jQuery.swap( elem, cssShow, function() {
+						val = getWH( elem, name, extra );
+					});
+				}
+
+				return val;
+			}
+		},
+
+		set: function( elem, value ) {
+			if ( rnumpx.test( value ) ) {
+				// ignore negative width and height values #1599
+				value = parseFloat( value );
+
+				if ( value >= 0 ) {
+					return value + "px";
+				}
+
+			} else {
+				return value;
+			}
+		}
+	};
+});
+
+if ( !jQuery.support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+				( parseFloat( RegExp.$1 ) / 100 ) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style,
+				currentStyle = elem.currentStyle;
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// Set the alpha filter to set the opacity
+			var opacity = jQuery.isNaN( value ) ?
+				"" :
+				"alpha(opacity=" + value * 100 + ")",
+				filter = currentStyle && currentStyle.filter || style.filter || "";
+
+			style.filter = ralpha.test( filter ) ?
+				filter.replace( ralpha, opacity ) :
+				filter + " " + opacity;
+		}
+	};
+}
+
+jQuery(function() {
+	// This hook cannot be added until DOM ready because the support test
+	// for it is not run until after DOM ready
+	if ( !jQuery.support.reliableMarginRight ) {
+		jQuery.cssHooks.marginRight = {
+			get: function( elem, computed ) {
+				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+				// Work around by temporarily setting element display to inline-block
+				var ret;
+				jQuery.swap( elem, { "display": "inline-block" }, function() {
+					if ( computed ) {
+						ret = curCSS( elem, "margin-right", "marginRight" );
+					} else {
+						ret = elem.style.marginRight;
+					}
+				});
+				return ret;
+			}
+		};
+	}
+});
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+	getComputedStyle = function( elem, name ) {
+		var ret, defaultView, computedStyle;
+
+		name = name.replace( rupper, "-$1" ).toLowerCase();
+
+		if ( !(defaultView = elem.ownerDocument.defaultView) ) {
+			return undefined;
+		}
+
+		if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+			ret = computedStyle.getPropertyValue( name );
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+		}
+
+		return ret;
+	};
+}
+
+if ( document.documentElement.currentStyle ) {
+	currentStyle = function( elem, name ) {
+		var left,
+			ret = elem.currentStyle && elem.currentStyle[ name ],
+			rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
+			style = elem.style;
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+			// Remember the original values
+			left = style.left;
+
+			// Put in the new values to get a computed value out
+			if ( rsLeft ) {
+				elem.runtimeStyle.left = elem.currentStyle.left;
+			}
+			style.left = name === "fontSize" ? "1em" : (ret || 0);
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			if ( rsLeft ) {
+				elem.runtimeStyle.left = rsLeft;
+			}
+		}
+
+		return ret === "" ? "auto" : ret;
+	};
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+
+	// Start with offset property
+	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		which = name === "width" ? cssWidth : cssHeight;
+
+	if ( val > 0 ) {
+		if ( extra !== "border" ) {
+			jQuery.each( which, function() {
+				if ( !extra ) {
+					val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
+				}
+				if ( extra === "margin" ) {
+					val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
+				} else {
+					val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
+				}
+			});
+		}
+
+		return val + "px";
+	}
+
+	// Fall back to computed then uncomputed css if necessary
+	val = curCSS( elem, name, name );
+	if ( val < 0 || val == null ) {
+		val = elem.style[ name ] || 0;
+	}
+	// Normalize "", auto, and prepare for extra
+	val = parseFloat( val ) || 0;
+
+	// Add padding, border, margin
+	if ( extra ) {
+		jQuery.each( which, function() {
+			val += parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
+			if ( extra !== "padding" ) {
+				val += parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
+			}
+			if ( extra === "margin" ) {
+				val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
+			}
+		});
+	}
+
+	return val + "px";
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.hidden = function( elem ) {
+		var width = elem.offsetWidth,
+			height = elem.offsetHeight;
+
+		return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
+	};
+
+	jQuery.expr.filters.visible = function( elem ) {
+		return !jQuery.expr.filters.hidden( elem );
+	};
+}
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rhash = /#.*$/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+	rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rquery = /\?/,
+	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+	rselectTextarea = /^(?:select|textarea)/i,
+	rspacesAjax = /\s+/,
+	rts = /([?&])_=[^&]*/,
+	rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+
+	// Keep a copy of the old load method
+	_load = jQuery.fn.load,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Document location
+	ajaxLocation,
+
+	// Document location segments
+	ajaxLocParts;
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+	ajaxLocation = location.href;
+} catch( e ) {
+	// Use the href attribute of an A element
+	// since IE will modify it given document.location
+	ajaxLocation = document.createElement( "a" );
+	ajaxLocation.href = "";
+	ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		if ( jQuery.isFunction( func ) ) {
+			var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+				i = 0,
+				length = dataTypes.length,
+				dataType,
+				list,
+				placeBefore;
+
+			// For each dataType in the dataTypeExpression
+			for(; i < length; i++ ) {
+				dataType = dataTypes[ i ];
+				// We control if we're asked to add before
+				// any existing element
+				placeBefore = /^\+/.test( dataType );
+				if ( placeBefore ) {
+					dataType = dataType.substr( 1 ) || "*";
+				}
+				list = structure[ dataType ] = structure[ dataType ] || [];
+				// then we add to the structure accordingly
+				list[ placeBefore ? "unshift" : "push" ]( func );
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+		dataType /* internal */, inspected /* internal */ ) {
+
+	dataType = dataType || options.dataTypes[ 0 ];
+	inspected = inspected || {};
+
+	inspected[ dataType ] = true;
+
+	var list = structure[ dataType ],
+		i = 0,
+		length = list ? list.length : 0,
+		executeOnly = ( structure === prefilters ),
+		selection;
+
+	for(; i < length && ( executeOnly || !selection ); i++ ) {
+		selection = list[ i ]( options, originalOptions, jqXHR );
+		// If we got redirected to another dataType
+		// we try there if executing only and not done already
+		if ( typeof selection === "string" ) {
+			if ( !executeOnly || inspected[ selection ] ) {
+				selection = undefined;
+			} else {
+				options.dataTypes.unshift( selection );
+				selection = inspectPrefiltersOrTransports(
+						structure, options, originalOptions, jqXHR, selection, inspected );
+			}
+		}
+	}
+	// If we're only executing or nothing was selected
+	// we try the catchall dataType if not done already
+	if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+		selection = inspectPrefiltersOrTransports(
+				structure, options, originalOptions, jqXHR, "*", inspected );
+	}
+	// unnecessary when only executing (prefilters)
+	// but it'll be ignored by the caller in that case
+	return selection;
+}
+
+jQuery.fn.extend({
+	load: function( url, params, callback ) {
+		if ( typeof url !== "string" && _load ) {
+			return _load.apply( this, arguments );
+
+		// Don't do a request if no elements are being requested
+		} else if ( !this.length ) {
+			return this;
+		}
+
+		var off = url.indexOf( " " );
+		if ( off >= 0 ) {
+			var selector = url.slice( off, url.length );
+			url = url.slice( 0, off );
+		}
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params ) {
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = undefined;
+
+			// Otherwise, build a param string
+			} else if ( typeof params === "object" ) {
+				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+				type = "POST";
+			}
+		}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			// Complete callback (responseText is used internally)
+			complete: function( jqXHR, status, responseText ) {
+				// Store the response as specified by the jqXHR object
+				responseText = jqXHR.responseText;
+				// If successful, inject the HTML into all the matched elements
+				if ( jqXHR.isResolved() ) {
+					// #4825: Get the actual response in case
+					// a dataFilter is present in ajaxSettings
+					jqXHR.done(function( r ) {
+						responseText = r;
+					});
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(responseText.replace(rscript, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						responseText );
+				}
+
+				if ( callback ) {
+					self.each( callback, [ responseText, status, jqXHR ] );
+				}
+			}
+		});
+
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+
+	serializeArray: function() {
+		return this.map(function(){
+			return this.elements ? jQuery.makeArray( this.elements ) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled &&
+				( this.checked || rselectTextarea.test( this.nodeName ) ||
+					rinput.test( this.type ) );
+		})
+		.map(function( i, elem ){
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val, i ){
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+	jQuery.fn[ o ] = function( f ){
+		return this.bind( o, f );
+	};
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			type: method,
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	};
+});
+
+jQuery.extend({
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function ( target, settings ) {
+		if ( !settings ) {
+			// Only one parameter, we extend ajaxSettings
+			settings = target;
+			target = jQuery.extend( true, jQuery.ajaxSettings, settings );
+		} else {
+			// target was provided, we extend into it
+			jQuery.extend( true, target, jQuery.ajaxSettings, settings );
+		}
+		// Flatten fields we don't want deep extended
+		for( var field in { context: 1, url: 1 } ) {
+			if ( field in settings ) {
+				target[ field ] = settings[ field ];
+			} else if( field in jQuery.ajaxSettings ) {
+				target[ field ] = jQuery.ajaxSettings[ field ];
+			}
+		}
+		return target;
+	},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		type: "GET",
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			text: "text/plain",
+			json: "application/json, text/javascript",
+			"*": "*/*"
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText"
+		},
+
+		// List of data converters
+		// 1) key format is "source_type destination_type" (a single space in-between)
+		// 2) the catchall symbol "*" can be used for source_type
+		converters: {
+
+			// Convert anything to text
+			"* text": window.String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		}
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var // Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events
+			// It's the callbackContext if one was provided in the options
+			// and if it's a DOM node or a jQuery collection
+			globalEventContext = callbackContext !== s &&
+				( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+						jQuery( callbackContext ) : jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery._Deferred(),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// ifModified key
+			ifModifiedKey,
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// Response headers
+			responseHeadersString,
+			responseHeaders,
+			// transport
+			transport,
+			// timeout handle
+			timeoutTimer,
+			// Cross-domain detection vars
+			parts,
+			// The jqXHR state
+			state = 0,
+			// To know if global events are to be dispatched
+			fireGlobals,
+			// Loop variable
+			i,
+			// Fake xhr
+			jqXHR = {
+
+				readyState: 0,
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					if ( !state ) {
+						var lname = name.toLowerCase();
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match === undefined ? null : match;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					statusText = statusText || "abort";
+					if ( transport ) {
+						transport.abort( statusText );
+					}
+					done( 0, statusText );
+					return this;
+				}
+			};
+
+		// Callback for when everything is done
+		// It is defined here because jslint complains if it is declared
+		// at the end of the function (which would be more logical and readable)
+		function done( status, statusText, responses, headers ) {
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status ? 4 : 0;
+
+			var isSuccess,
+				success,
+				error,
+				response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+				lastModified,
+				etag;
+
+			// If successful, handle type chaining
+			if ( status >= 200 && status < 300 || status === 304 ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+
+					if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+						jQuery.lastModified[ ifModifiedKey ] = lastModified;
+					}
+					if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+						jQuery.etag[ ifModifiedKey ] = etag;
+					}
+				}
+
+				// If not modified
+				if ( status === 304 ) {
+
+					statusText = "notmodified";
+					isSuccess = true;
+
+				// If we have data
+				} else {
+
+					try {
+						success = ajaxConvert( s, response );
+						statusText = "success";
+						isSuccess = true;
+					} catch(e) {
+						// We have a parsererror
+						statusText = "parsererror";
+						error = e;
+					}
+				}
+			} else {
+				// We extract error from statusText
+				// then normalize statusText and status for non-aborts
+				error = statusText;
+				if( !statusText || status ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = statusText;
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+						[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger( "ajaxStop" );
+				}
+			}
+		}
+
+		// Attach deferreds
+		deferred.promise( jqXHR );
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+		jqXHR.complete = completeDeferred.done;
+
+		// Status-dependent callbacks
+		jqXHR.statusCode = function( map ) {
+			if ( map ) {
+				var tmp;
+				if ( state < 2 ) {
+					for( tmp in map ) {
+						statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+					}
+				} else {
+					tmp = map[ jqXHR.status ];
+					jqXHR.then( tmp, tmp );
+				}
+			}
+			return this;
+		};
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+		// Determine if a cross-domain request is in order
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() );
+			s.crossDomain = !!( parts &&
+				( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+			);
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefiler, stop there
+		if ( state === 2 ) {
+			return false;
+		}
+
+		// We can fire global events as of now if asked to
+		fireGlobals = s.global;
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger( "ajaxStart" );
+		}
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+			}
+
+			// Get ifModifiedKey before adding the anti-cache parameter
+			ifModifiedKey = s.url;
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+
+				var ts = jQuery.now(),
+					// try replacing _= if it is there
+					ret = s.url.replace( rts, "$1_=" + ts );
+
+				// if nothing was replaced, add timestamp to the end
+				s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			ifModifiedKey = ifModifiedKey || s.url;
+			if ( jQuery.lastModified[ ifModifiedKey ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+			}
+			if ( jQuery.etag[ ifModifiedKey ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+			}
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+				// Abort if not done already
+				jqXHR.abort();
+				return false;
+
+		}
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout( function(){
+					jqXHR.abort( "timeout" );
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch (e) {
+				// Propagate exception as error if not done
+				if ( status < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					jQuery.error( e );
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a, traditional ) {
+		var s = [],
+			add = function( key, value ) {
+				// If value is a function, invoke it and return its value
+				value = jQuery.isFunction( value ) ? value() : value;
+				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+			};
+
+		// Set traditional to true for jQuery <= 1.3.2 behavior.
+		if ( traditional === undefined ) {
+			traditional = jQuery.ajaxSettings.traditional;
+		}
+
+		// If an array was passed in, assume that it is an array of form elements.
+		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+			// Serialize the form elements
+			jQuery.each( a, function() {
+				add( this.name, this.value );
+			});
+
+		} else {
+			// If traditional, encode the "old" way (the way 1.3.2 or older
+			// did it), otherwise encode params recursively.
+			for ( var prefix in a ) {
+				buildParams( prefix, a[ prefix ], traditional, add );
+			}
+		}
+
+		// Return the resulting serialization
+		return s.join( "&" ).replace( r20, "+" );
+	}
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// If array item is non-scalar (array or object), encode its
+				// numeric index to resolve deserialization ambiguity issues.
+				// Note that rack (as of 1.0.0) can't currently deserialize
+				// nested arrays properly, and attempting to do so may cause
+				// a server error. Possible fixes are to modify rack's
+				// deserialization algorithm or to provide an option or flag
+				// to force array serialization to be shallow.
+				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && obj != null && typeof obj === "object" ) {
+		// Serialize object item.
+		for ( var name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+	var contents = s.contents,
+		dataTypes = s.dataTypes,
+		responseFields = s.responseFields,
+		ct,
+		type,
+		finalDataType,
+		firstDataType;
+
+	// Fill responseXXX fields
+	for( type in responseFields ) {
+		if ( type in responses ) {
+			jqXHR[ responseFields[type] ] = responses[ type ];
+		}
+	}
+
+	// Remove auto dataType and get content-type in the process
+	while( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+	// Apply the dataFilter if provided
+	if ( s.dataFilter ) {
+		response = s.dataFilter( response, s.dataType );
+	}
+
+	var dataTypes = s.dataTypes,
+		converters = {},
+		i,
+		key,
+		length = dataTypes.length,
+		tmp,
+		// Current and previous dataTypes
+		current = dataTypes[ 0 ],
+		prev,
+		// Conversion expression
+		conversion,
+		// Conversion function
+		conv,
+		// Conversion functions (transitive conversion)
+		conv1,
+		conv2;
+
+	// For each dataType in the chain
+	for( i = 1; i < length; i++ ) {
+
+		// Create converters map
+		// with lowercased keys
+		if ( i === 1 ) {
+			for( key in s.converters ) {
+				if( typeof key === "string" ) {
+					converters[ key.toLowerCase() ] = s.converters[ key ];
+				}
+			}
+		}
+
+		// Get the dataTypes
+		prev = current;
+		current = dataTypes[ i ];
+
+		// If current is auto dataType, update it to prev
+		if( current === "*" ) {
+			current = prev;
+		// If no auto and dataTypes are actually different
+		} else if ( prev !== "*" && prev !== current ) {
+
+			// Get the converter
+			conversion = prev + " " + current;
+			conv = converters[ conversion ] || converters[ "* " + current ];
+
+			// If there is no direct converter, search transitively
+			if ( !conv ) {
+				conv2 = undefined;
+				for( conv1 in converters ) {
+					tmp = conv1.split( " " );
+					if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+						conv2 = converters[ tmp[1] + " " + current ];
+						if ( conv2 ) {
+							conv1 = converters[ conv1 ];
+							if ( conv1 === true ) {
+								conv = conv2;
+							} else if ( conv2 === true ) {
+								conv = conv1;
+							}
+							break;
+						}
+					}
+				}
+			}
+			// If we found no converter, dispatch an error
+			if ( !( conv || conv2 ) ) {
+				jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+			}
+			// If found converter is not an equivalence
+			if ( conv !== true ) {
+				// Convert with 1 or 2 converters accordingly
+				response = conv ? conv( response ) : conv2( conv1(response) );
+			}
+		}
+	}
+	return response;
+}
+
+
+
+
+var jsc = jQuery.now(),
+	jsre = /(\=)\?(&|$)|\?\?/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		return jQuery.expando + "_" + ( jsc++ );
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
+		( typeof s.data === "string" );
+
+	if ( s.dataTypes[ 0 ] === "jsonp" ||
+		s.jsonp !== false && ( jsre.test( s.url ) ||
+				inspectData && jsre.test( s.data ) ) ) {
+
+		var responseContainer,
+			jsonpCallback = s.jsonpCallback =
+				jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+			previous = window[ jsonpCallback ],
+			url = s.url,
+			data = s.data,
+			replace = "$1" + jsonpCallback + "$2";
+
+		if ( s.jsonp !== false ) {
+			url = url.replace( jsre, replace );
+			if ( s.url === url ) {
+				if ( inspectData ) {
+					data = data.replace( jsre, replace );
+				}
+				if ( s.data === data ) {
+					// Add callback manually
+					url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+				}
+			}
+		}
+
+		s.url = url;
+		s.data = data;
+
+		// Install callback
+		window[ jsonpCallback ] = function( response ) {
+			responseContainer = [ response ];
+		};
+
+		// Clean-up function
+		jqXHR.always(function() {
+			// Set callback back to previous value
+			window[ jsonpCallback ] = previous;
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( previous ) ) {
+				window[ jsonpCallback ]( responseContainer[ 0 ] );
+			}
+		});
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( jsonpCallback + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Delegate to script
+		return "script";
+	}
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /javascript|ecmascript/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+		s.global = false;
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+
+		var script,
+			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+		return {
+
+			send: function( _, callback ) {
+
+				script = document.createElement( "script" );
+
+				script.async = "async";
+
+				if ( s.scriptCharset ) {
+					script.charset = s.scriptCharset;
+				}
+
+				script.src = s.url;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+
+						// Remove the script
+						if ( head && script.parentNode ) {
+							head.removeChild( script );
+						}
+
+						// Dereference the script
+						script = undefined;
+
+						// Callback if not abort
+						if ( !isAbort ) {
+							callback( 200, "success" );
+						}
+					}
+				};
+				// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+				// This arises when a base node is used (#2709 and #4378).
+				head.insertBefore( script, head.firstChild );
+			},
+
+			abort: function() {
+				if ( script ) {
+					script.onload( 0, 1 );
+				}
+			}
+		};
+	}
+});
+
+
+
+
+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+	xhrOnUnloadAbort = window.ActiveXObject ? function() {
+		// Abort all pending requests
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]( 0, 1 );
+		}
+	} : false,
+	xhrId = 0,
+	xhrCallbacks;
+
+// Functions to create xhrs
+function createStandardXHR() {
+	try {
+		return new window.XMLHttpRequest();
+	} catch( e ) {}
+}
+
+function createActiveXHR() {
+	try {
+		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+	} catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+	/* Microsoft failed to properly
+	 * implement the XMLHttpRequest in IE7 (can't request local files),
+	 * so we use the ActiveXObject when it is available
+	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+	 * we need a fallback.
+	 */
+	function() {
+		return !this.isLocal && createStandardXHR() || createActiveXHR();
+	} :
+	// For all other browsers, use the standard XMLHttpRequest object
+	createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+	jQuery.extend( jQuery.support, {
+		ajax: !!xhr,
+		cors: !!xhr && ( "withCredentials" in xhr )
+	});
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+	jQuery.ajaxTransport(function( s ) {
+		// Cross domain only allowed if supported through XMLHttpRequest
+		if ( !s.crossDomain || jQuery.support.cors ) {
+
+			var callback;
+
+			return {
+				send: function( headers, complete ) {
+
+					// Get a new xhr
+					var xhr = s.xhr(),
+						handle,
+						i;
+
+					// Open the socket
+					// Passing null username, generates a login popup on Opera (#2865)
+					if ( s.username ) {
+						xhr.open( s.type, s.url, s.async, s.username, s.password );
+					} else {
+						xhr.open( s.type, s.url, s.async );
+					}
+
+					// Apply custom fields if provided
+					if ( s.xhrFields ) {
+						for ( i in s.xhrFields ) {
+							xhr[ i ] = s.xhrFields[ i ];
+						}
+					}
+
+					// Override mime type if needed
+					if ( s.mimeType && xhr.overrideMimeType ) {
+						xhr.overrideMimeType( s.mimeType );
+					}
+
+					// X-Requested-With header
+					// For cross-domain requests, seeing as conditions for a preflight are
+					// akin to a jigsaw puzzle, we simply never set it to be sure.
+					// (it can always be set on a per-request basis or even using ajaxSetup)
+					// For same-domain requests, won't change header if already provided.
+					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+						headers[ "X-Requested-With" ] = "XMLHttpRequest";
+					}
+
+					// Need an extra try/catch for cross domain requests in Firefox 3
+					try {
+						for ( i in headers ) {
+							xhr.setRequestHeader( i, headers[ i ] );
+						}
+					} catch( _ ) {}
+
+					// Do send the request
+					// This may raise an exception which is actually
+					// handled in jQuery.ajax (so no try/catch here)
+					xhr.send( ( s.hasContent && s.data ) || null );
+
+					// Listener
+					callback = function( _, isAbort ) {
+
+						var status,
+							statusText,
+							responseHeaders,
+							responses,
+							xml;
+
+						// Firefox throws exceptions when accessing properties
+						// of an xhr when a network error occured
+						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+						try {
+
+							// Was never called and is aborted or complete
+							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+								// Only called once
+								callback = undefined;
+
+								// Do not keep as active anymore
+								if ( handle ) {
+									xhr.onreadystatechange = jQuery.noop;
+									if ( xhrOnUnloadAbort ) {
+										delete xhrCallbacks[ handle ];
+									}
+								}
+
+								// If it's an abort
+								if ( isAbort ) {
+									// Abort it manually if needed
+									if ( xhr.readyState !== 4 ) {
+										xhr.abort();
+									}
+								} else {
+									status = xhr.status;
+									responseHeaders = xhr.getAllResponseHeaders();
+									responses = {};
+									xml = xhr.responseXML;
+
+									// Construct response list
+									if ( xml && xml.documentElement /* #4958 */ ) {
+										responses.xml = xml;
+									}
+									responses.text = xhr.responseText;
+
+									// Firefox throws an exception when accessing
+									// statusText for faulty cross-domain requests
+									try {
+										statusText = xhr.statusText;
+									} catch( e ) {
+										// We normalize with Webkit giving an empty statusText
+										statusText = "";
+									}
+
+									// Filter status for non standard behaviors
+
+									// If the request is local and we have data: assume a success
+									// (success with no data won't get notified, that's the best we
+									// can do given current implementations)
+									if ( !status && s.isLocal && !s.crossDomain ) {
+										status = responses.text ? 200 : 404;
+									// IE - #1450: sometimes returns 1223 when it should be 204
+									} else if ( status === 1223 ) {
+										status = 204;
+									}
+								}
+							}
+						} catch( firefoxAccessException ) {
+							if ( !isAbort ) {
+								complete( -1, firefoxAccessException );
+							}
+						}
+
+						// Call complete if needed
+						if ( responses ) {
+							complete( status, statusText, responses, responseHeaders );
+						}
+					};
+
+					// if we're in sync mode or it's in cache
+					// and has been retrieved directly (IE6 & IE7)
+					// we need to manually fire the callback
+					if ( !s.async || xhr.readyState === 4 ) {
+						callback();
+					} else {
+						handle = ++xhrId;
+						if ( xhrOnUnloadAbort ) {
+							// Create the active xhrs callbacks list if needed
+							// and attach the unload handler
+							if ( !xhrCallbacks ) {
+								xhrCallbacks = {};
+								jQuery( window ).unload( xhrOnUnloadAbort );
+							}
+							// Add to list of active xhrs callbacks
+							xhrCallbacks[ handle ] = callback;
+						}
+						xhr.onreadystatechange = callback;
+					}
+				},
+
+				abort: function() {
+					if ( callback ) {
+						callback(0,1);
+					}
+				}
+			};
+		}
+	});
+}
+
+
+
+
+var elemdisplay = {},
+	iframe, iframeDoc,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+	timerId,
+	fxAttrs = [
+		// height animations
+		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+		// width animations
+		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+		// opacity animations
+		[ "opacity" ]
+	],
+	fxNow,
+	requestAnimationFrame = window.webkitRequestAnimationFrame ||
+		window.mozRequestAnimationFrame ||
+		window.oRequestAnimationFrame;
+
+jQuery.fn.extend({
+	show: function( speed, easing, callback ) {
+		var elem, display;
+
+		if ( speed || speed === 0 ) {
+			return this.animate( genFx("show", 3), speed, easing, callback);
+
+		} else {
+			for ( var i = 0, j = this.length; i < j; i++ ) {
+				elem = this[i];
+
+				if ( elem.style ) {
+					display = elem.style.display;
+
+					// Reset the inline display of this element to learn if it is
+					// being hidden by cascaded rules or not
+					if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+						display = elem.style.display = "";
+					}
+
+					// Set elements which have been overridden with display: none
+					// in a stylesheet to whatever the default browser style is
+					// for such an element
+					if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
+						jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
+					}
+				}
+			}
+
+			// Set the display of most of the elements in a second loop
+			// to avoid the constant reflow
+			for ( i = 0; i < j; i++ ) {
+				elem = this[i];
+
+				if ( elem.style ) {
+					display = elem.style.display;
+
+					if ( display === "" || display === "none" ) {
+						elem.style.display = jQuery._data(elem, "olddisplay") || "";
+					}
+				}
+			}
+
+			return this;
+		}
+	},
+
+	hide: function( speed, easing, callback ) {
+		if ( speed || speed === 0 ) {
+			return this.animate( genFx("hide", 3), speed, easing, callback);
+
+		} else {
+			for ( var i = 0, j = this.length; i < j; i++ ) {
+				if ( this[i].style ) {
+					var display = jQuery.css( this[i], "display" );
+
+					if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
+						jQuery._data( this[i], "olddisplay", display );
+					}
+				}
+			}
+
+			// Set the display of the elements in a second loop
+			// to avoid the constant reflow
+			for ( i = 0; i < j; i++ ) {
+				if ( this[i].style ) {
+					this[i].style.display = "none";
+				}
+			}
+
+			return this;
+		}
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+
+	toggle: function( fn, fn2, callback ) {
+		var bool = typeof fn === "boolean";
+
+		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+			this._toggle.apply( this, arguments );
+
+		} else if ( fn == null || bool ) {
+			this.each(function() {
+				var state = bool ? fn : jQuery(this).is(":hidden");
+				jQuery(this)[ state ? "show" : "hide" ]();
+			});
+
+		} else {
+			this.animate(genFx("toggle", 3), fn, fn2, callback);
+		}
+
+		return this;
+	},
+
+	fadeTo: function( speed, to, easing, callback ) {
+		return this.filter(":hidden").css("opacity", 0).show().end()
+					.animate({opacity: to}, speed, easing, callback);
+	},
+
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		if ( jQuery.isEmptyObject( prop ) ) {
+			return this.each( optall.complete, [ false ] );
+		}
+
+		// Do not change referenced properties as per-property easing will be lost
+		prop = jQuery.extend( {}, prop );
+
+		return this[ optall.queue === false ? "each" : "queue" ](function() {
+			// XXX 'this' does not always have a nodeName when running the
+			// test suite
+
+			if ( optall.queue === false ) {
+				jQuery._mark( this );
+			}
+
+			var opt = jQuery.extend( {}, optall ),
+				isElement = this.nodeType === 1,
+				hidden = isElement && jQuery(this).is(":hidden"),
+				name, val, p,
+				display, e,
+				parts, start, end, unit;
+
+			// will store per property easing and be used to determine when an animation is complete
+			opt.animatedProperties = {};
+
+			for ( p in prop ) {
+
+				// property name normalization
+				name = jQuery.camelCase( p );
+				if ( p !== name ) {
+					prop[ name ] = prop[ p ];
+					delete prop[ p ];
+				}
+
+				val = prop[ name ];
+
+				// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+				if ( jQuery.isArray( val ) ) {
+					opt.animatedProperties[ name ] = val[ 1 ];
+					val = prop[ name ] = val[ 0 ];
+				} else {
+					opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+				}
+
+				if ( val === "hide" && hidden || val === "show" && !hidden ) {
+					return opt.complete.call( this );
+				}
+
+				if ( isElement && ( name === "height" || name === "width" ) ) {
+					// Make sure that nothing sneaks out
+					// Record all 3 overflow attributes because IE does not
+					// change the overflow attribute when overflowX and
+					// overflowY are set to the same value
+					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+					// Set display property to inline-block for height/width
+					// animations on inline elements that are having width/height
+					// animated
+					if ( jQuery.css( this, "display" ) === "inline" &&
+							jQuery.css( this, "float" ) === "none" ) {
+						if ( !jQuery.support.inlineBlockNeedsLayout ) {
+							this.style.display = "inline-block";
+
+						} else {
+							display = defaultDisplay( this.nodeName );
+
+							// inline-level elements accept inline-block;
+							// block-level elements need to be inline with layout
+							if ( display === "inline" ) {
+								this.style.display = "inline-block";
+
+							} else {
+								this.style.display = "inline";
+								this.style.zoom = 1;
+							}
+						}
+					}
+				}
+			}
+
+			if ( opt.overflow != null ) {
+				this.style.overflow = "hidden";
+			}
+
+			for ( p in prop ) {
+				e = new jQuery.fx( this, opt, p );
+				val = prop[ p ];
+
+				if ( rfxtypes.test(val) ) {
+					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]();
+
+				} else {
+					parts = rfxnum.exec( val );
+					start = e.cur();
+
+					if ( parts ) {
+						end = parseFloat( parts[2] );
+						unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+						// We need to compute starting value
+						if ( unit !== "px" ) {
+							jQuery.style( this, p, (end || 1) + unit);
+							start = ((end || 1) / e.cur()) * start;
+							jQuery.style( this, p, start + unit);
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] ) {
+							end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+						}
+
+						e.custom( start, end, unit );
+
+					} else {
+						e.custom( start, val, "" );
+					}
+				}
+			}
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+
+	stop: function( clearQueue, gotoEnd ) {
+		if ( clearQueue ) {
+			this.queue([]);
+		}
+
+		this.each(function() {
+			var timers = jQuery.timers,
+				i = timers.length;
+			// clear marker counters if we know they won't be
+			if ( !gotoEnd ) {
+				jQuery._unmark( true, this );
+			}
+			while ( i-- ) {
+				if ( timers[i].elem === this ) {
+					if (gotoEnd) {
+						// force the next step to be the last
+						timers[i](true);
+					}
+
+					timers.splice(i, 1);
+				}
+			}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if ( !gotoEnd ) {
+			this.dequeue();
+		}
+
+		return this;
+	}
+
+});
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout( clearFxNow, 0 );
+	return ( fxNow = jQuery.now() );
+}
+
+function clearFxNow() {
+	fxNow = undefined;
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, num ) {
+	var obj = {};
+
+	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+		obj[ this ] = type;
+	});
+
+	return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show", 1),
+	slideUp: genFx("hide", 1),
+	slideToggle: genFx("toggle", 1),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.extend({
+	speed: function( speed, easing, fn ) {
+		var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
+			complete: fn || !fn && easing ||
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+		};
+
+		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
+
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function( noUnmark ) {
+			if ( jQuery.isFunction( opt.old ) ) {
+				opt.old.call( this );
+			}
+
+			if ( opt.queue !== false ) {
+				jQuery.dequeue( this );
+			} else if ( noUnmark !== false ) {
+				jQuery._unmark( this );
+			}
+		};
+
+		return opt;
+	},
+
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+
+	timers: [],
+
+	fx: function( elem, options, prop ) {
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		options.orig = options.orig || {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+	// Simple function for setting a style value
+	update: function() {
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+	},
+
+	// Get the current size
+	cur: function() {
+		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
+			return this.elem[ this.prop ];
+		}
+
+		var parsed,
+			r = jQuery.css( this.elem, this.prop );
+		// Empty strings, null, undefined and "auto" are converted to 0,
+		// complex values such as "rotate(1rad)" are returned as is,
+		// simple values such as "10px" are parsed to Float.
+		return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+	},
+
+	// Start an animation from one number to another
+	custom: function( from, to, unit ) {
+		var self = this,
+			fx = jQuery.fx,
+			raf;
+
+		this.startTime = fxNow || createFxNow();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+		this.now = this.start;
+		this.pos = this.state = 0;
+
+		function t( gotoEnd ) {
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		if ( t() && jQuery.timers.push(t) && !timerId ) {
+			// Use requestAnimationFrame instead of setInterval if available
+			if ( requestAnimationFrame ) {
+				timerId = true;
+				raf = function() {
+					// When timerId gets set to null at any point, this stops
+					if ( timerId ) {
+						requestAnimationFrame( raf );
+						fx.tick();
+					}
+				};
+				requestAnimationFrame( raf );
+			} else {
+				timerId = setInterval( fx.tick, fx.interval );
+			}
+		}
+	},
+
+	// Simple 'show' function
+	show: function() {
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
+
+		// Start by showing the element
+		jQuery( this.elem ).show();
+	},
+
+	// Simple 'hide' function
+	hide: function() {
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function( gotoEnd ) {
+		var t = fxNow || createFxNow(),
+			done = true,
+			elem = this.elem,
+			options = this.options,
+			i, n;
+
+		if ( gotoEnd || t >= options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			options.animatedProperties[ this.prop ] = true;
+
+			for ( i in options.animatedProperties ) {
+				if ( options.animatedProperties[i] !== true ) {
+					done = false;
+				}
+			}
+
+			if ( done ) {
+				// Reset the overflow
+				if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+
+					jQuery.each( [ "", "X", "Y" ], function (index, value) {
+						elem.style[ "overflow" + value ] = options.overflow[index];
+					});
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( options.hide ) {
+					jQuery(elem).hide();
+				}
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( options.hide || options.show ) {
+					for ( var p in options.animatedProperties ) {
+						jQuery.style( elem, p, options.orig[p] );
+					}
+				}
+
+				// Execute the complete function
+				options.complete.call( elem );
+			}
+
+			return false;
+
+		} else {
+			// classical easing cannot be used with an Infinity duration
+			if ( options.duration == Infinity ) {
+				this.now = t;
+			} else {
+				n = t - this.startTime;
+				this.state = n / options.duration;
+
+				// Perform the easing function, defaults to swing
+				this.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );
+				this.now = this.start + ((this.end - this.start) * this.pos);
+			}
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+};
+
+jQuery.extend( jQuery.fx, {
+	tick: function() {
+		for ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {
+			if ( !timers[i]() ) {
+				timers.splice(i--, 1);
+			}
+		}
+
+		if ( !timers.length ) {
+			jQuery.fx.stop();
+		}
+	},
+
+	interval: 13,
+
+	stop: function() {
+		clearInterval( timerId );
+		timerId = null;
+	},
+
+	speeds: {
+		slow: 600,
+		fast: 200,
+		// Default speed
+		_default: 400
+	},
+
+	step: {
+		opacity: function( fx ) {
+			jQuery.style( fx.elem, "opacity", fx.now );
+		},
+
+		_default: function( fx ) {
+			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+			} else {
+				fx.elem[ fx.prop ] = fx.now;
+			}
+		}
+	}
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.animated = function( elem ) {
+		return jQuery.grep(jQuery.timers, function( fn ) {
+			return elem === fn.elem;
+		}).length;
+	};
+}
+
+// Try to restore the default display value of an element
+function defaultDisplay( nodeName ) {
+
+	if ( !elemdisplay[ nodeName ] ) {
+
+		var body = document.body,
+			elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+			display = elem.css( "display" );
+
+		elem.remove();
+
+		// If the simple way fails,
+		// get element's real default display by attaching it to a temp iframe
+		if ( display === "none" || display === "" ) {
+			// No iframe to use yet, so create it
+			if ( !iframe ) {
+				iframe = document.createElement( "iframe" );
+				iframe.frameBorder = iframe.width = iframe.height = 0;
+			}
+
+			body.appendChild( iframe );
+
+			// Create a cacheable copy of the iframe document on first call.
+			// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+			// document to it; WebKit & Firefox won't allow reusing the iframe document.
+			if ( !iframeDoc || !iframe.createElement ) {
+				iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+				iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
+				iframeDoc.close();
+			}
+
+			elem = iframeDoc.createElement( nodeName );
+
+			iframeDoc.body.appendChild( elem );
+
+			display = jQuery.css( elem, "display" );
+
+			body.removeChild( iframe );
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+	rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+	jQuery.fn.offset = function( options ) {
+		var elem = this[0], box;
+
+		if ( options ) {
+			return this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+		}
+
+		if ( !elem || !elem.ownerDocument ) {
+			return null;
+		}
+
+		if ( elem === elem.ownerDocument.body ) {
+			return jQuery.offset.bodyOffset( elem );
+		}
+
+		try {
+			box = elem.getBoundingClientRect();
+		} catch(e) {}
+
+		var doc = elem.ownerDocument,
+			docElem = doc.documentElement;
+
+		// Make sure we're not dealing with a disconnected DOM node
+		if ( !box || !jQuery.contains( docElem, elem ) ) {
+			return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+		}
+
+		var body = doc.body,
+			win = getWindow(doc),
+			clientTop  = docElem.clientTop  || body.clientTop  || 0,
+			clientLeft = docElem.clientLeft || body.clientLeft || 0,
+			scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
+			scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+			top  = box.top  + scrollTop  - clientTop,
+			left = box.left + scrollLeft - clientLeft;
+
+		return { top: top, left: left };
+	};
+
+} else {
+	jQuery.fn.offset = function( options ) {
+		var elem = this[0];
+
+		if ( options ) {
+			return this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+		}
+
+		if ( !elem || !elem.ownerDocument ) {
+			return null;
+		}
+
+		if ( elem === elem.ownerDocument.body ) {
+			return jQuery.offset.bodyOffset( elem );
+		}
+
+		jQuery.offset.initialize();
+
+		var computedStyle,
+			offsetParent = elem.offsetParent,
+			prevOffsetParent = elem,
+			doc = elem.ownerDocument,
+			docElem = doc.documentElement,
+			body = doc.body,
+			defaultView = doc.defaultView,
+			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+			top = elem.offsetTop,
+			left = elem.offsetLeft;
+
+		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+				break;
+			}
+
+			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+			top  -= elem.scrollTop;
+			left -= elem.scrollLeft;
+
+			if ( elem === offsetParent ) {
+				top  += elem.offsetTop;
+				left += elem.offsetLeft;
+
+				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+				}
+
+				prevOffsetParent = offsetParent;
+				offsetParent = elem.offsetParent;
+			}
+
+			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+			}
+
+			prevComputedStyle = computedStyle;
+		}
+
+		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+			top  += body.offsetTop;
+			left += body.offsetLeft;
+		}
+
+		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+			top  += Math.max( docElem.scrollTop, body.scrollTop );
+			left += Math.max( docElem.scrollLeft, body.scrollLeft );
+		}
+
+		return { top: top, left: left };
+	};
+}
+
+jQuery.offset = {
+	initialize: function() {
+		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
+			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+
+		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
+
+		container.innerHTML = html;
+		body.insertBefore( container, body.firstChild );
+		innerDiv = container.firstChild;
+		checkDiv = innerDiv.firstChild;
+		td = innerDiv.nextSibling.firstChild.firstChild;
+
+		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+		checkDiv.style.position = "fixed";
+		checkDiv.style.top = "20px";
+
+		// safari subtracts parent border width here which is 5px
+		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+		checkDiv.style.position = checkDiv.style.top = "";
+
+		innerDiv.style.overflow = "hidden";
+		innerDiv.style.position = "relative";
+
+		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
+
+		body.removeChild( container );
+		jQuery.offset.initialize = jQuery.noop;
+	},
+
+	bodyOffset: function( body ) {
+		var top = body.offsetTop,
+			left = body.offsetLeft;
+
+		jQuery.offset.initialize();
+
+		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+		}
+
+		return { top: top, left: left };
+	},
+
+	setOffset: function( elem, options, i ) {
+		var position = jQuery.css( elem, "position" );
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		var curElem = jQuery( elem ),
+			curOffset = curElem.offset(),
+			curCSSTop = jQuery.css( elem, "top" ),
+			curCSSLeft = jQuery.css( elem, "left" ),
+			calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+			props = {}, curPosition = {}, curTop, curLeft;
+
+		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if (options.top != null) {
+			props.top = (options.top - curOffset.top) + curTop;
+		}
+		if (options.left != null) {
+			props.left = (options.left - curOffset.left) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+
+jQuery.fn.extend({
+	position: function() {
+		if ( !this[0] ) {
+			return null;
+		}
+
+		var elem = this[0],
+
+		// Get *real* offsetParent
+		offsetParent = this.offsetParent(),
+
+		// Get correct offsets
+		offset       = this.offset(),
+		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+		// Subtract element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+		// Add offsetParent borders
+		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+		// Subtract the two offsets
+		return {
+			top:  offset.top  - parentOffset.top,
+			left: offset.left - parentOffset.left
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || document.body;
+			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent;
+		});
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+	var method = "scroll" + name;
+
+	jQuery.fn[ method ] = function( val ) {
+		var elem, win;
+
+		if ( val === undefined ) {
+			elem = this[ 0 ];
+
+			if ( !elem ) {
+				return null;
+			}
+
+			win = getWindow( elem );
+
+			// Return the scroll offset
+			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+				jQuery.support.boxModel && win.document.documentElement[ method ] ||
+					win.document.body[ method ] :
+				elem[ method ];
+		}
+
+		// Set the scroll offset
+		return this.each(function() {
+			win = getWindow( this );
+
+			if ( win ) {
+				win.scrollTo(
+					!i ? val : jQuery( win ).scrollLeft(),
+					 i ? val : jQuery( win ).scrollTop()
+				);
+
+			} else {
+				this[ method ] = val;
+			}
+		});
+	};
+});
+
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+
+
+
+
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+	var type = name.toLowerCase();
+
+	// innerHeight and innerWidth
+	jQuery.fn[ "inner" + name ] = function() {
+		var elem = this[0];
+		return elem && elem.style ?
+			parseFloat( jQuery.css( elem, type, "padding" ) ) :
+			null;
+	};
+
+	// outerHeight and outerWidth
+	jQuery.fn[ "outer" + name ] = function( margin ) {
+		var elem = this[0];
+		return elem && elem.style ?
+			parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+			null;
+	};
+
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		var elem = this[0];
+		if ( !elem ) {
+			return size == null ? null : this;
+		}
+
+		if ( jQuery.isFunction( size ) ) {
+			return this.each(function( i ) {
+				var self = jQuery( this );
+				self[ type ]( size.call( this, i, self[ type ]() ) );
+			});
+		}
+
+		if ( jQuery.isWindow( elem ) ) {
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+			var docElemProp = elem.document.documentElement[ "client" + name ];
+			return elem.document.compatMode === "CSS1Compat" && docElemProp ||
+				elem.document.body[ "client" + name ] || docElemProp;
+
+		// Get document width or height
+		} else if ( elem.nodeType === 9 ) {
+			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+			return Math.max(
+				elem.documentElement["client" + name],
+				elem.body["scroll" + name], elem.documentElement["scroll" + name],
+				elem.body["offset" + name], elem.documentElement["offset" + name]
+			);
+
+		// Get or set width or height on the element
+		} else if ( size === undefined ) {
+			var orig = jQuery.css( elem, type ),
+				ret = parseFloat( orig );
+
+			return jQuery.isNaN( ret ) ? orig : ret;
+
+		// Set the width or height on the element (default to pixels if value is unitless)
+		} else {
+			return this.css( type, typeof size === "string" ? size : size + "px" );
+		}
+	};
+
+});
+
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+})(window);
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/mocha.css
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/mocha.css	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/mocha.css	(revision 533)
@@ -0,0 +1,163 @@
+
+body {
+  font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+  padding: 60px 50px;
+}
+
+#mocha h1, h2 {
+  margin: 0;
+}
+
+#mocha h1 {
+  margin-top: 15px;
+  font-size: 1em;
+  font-weight: 200;
+}
+
+#mocha .suite .suite h1 {
+  margin-top: 0;
+  font-size: .8em;
+}
+
+#mocha h2 {
+  font-size: 12px;
+  font-weight: normal;
+  cursor: pointer;
+}
+
+#mocha .suite {
+  margin-left: 15px;
+}
+
+#mocha .test {
+  margin-left: 15px;
+}
+
+#mocha .test:hover h2::after {
+  position: relative;
+  top: 0;
+  right: -10px;
+  content: '(view source)';
+  font-size: 12px;
+  font-family: arial;
+  color: #888;
+}
+
+#mocha .test.pending:hover h2::after {
+  content: '(pending)';
+  font-family: arial;
+}
+
+#mocha .test.pass.medium .duration {
+  background: #C09853;
+}
+
+#mocha .test.pass.slow .duration {
+  background: #B94A48;
+}
+
+#mocha .test.pass::before {
+  content: 'â';
+  font-size: 12px;
+  display: block;
+  float: left;
+  margin-right: 5px;
+}
+
+#mocha .test.pass .duration {
+  font-size: 9px;
+  margin-left: 5px;
+  padding: 2px 5px;
+  color: white;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+  -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+  box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  -ms-border-radius: 5px;
+  -o-border-radius: 5px;
+  border-radius: 5px;
+}
+
+#mocha .test.pass.fast .duration {
+  display: none;
+}
+
+#mocha .test.pending {
+  color: #0b97c4;
+}
+
+#mocha .test.pending::before {
+  content: 'âŠ';
+  color: #0b97c4;
+}
+
+#mocha .test.fail {
+  color: #c00;
+}
+
+#mocha .test.fail pre {
+  color: black;
+}
+
+#mocha .test.fail::before {
+  content: 'â';
+  font-size: 12px;
+  display: block;
+  float: left;
+  margin-right: 5px;
+  color: #c00;
+}
+
+#mocha .test pre.error {
+  color: #c00;
+}
+
+#mocha .test pre {
+  display: inline-block;
+  font: 12px/1.5 monaco, monospace;
+  margin: 5px;
+  padding: 15px;
+  border: 1px solid #eee;
+  border-bottom-color: #ddd;
+  -webkit-border-radius: 3px;
+  -webkit-box-shadow: 0 1px 3px #eee;
+}
+
+#error {
+  color: #c00;
+  font-size: 1.5  em;
+  font-weight: 100;
+  letter-spacing: 1px;
+}
+
+#stats {
+  position: fixed;
+  top: 15px;
+  right: 10px;
+  font-size: 12px;
+  margin: 0;
+  color: #888;
+}
+
+#stats .progress {
+  float: right;
+  padding-top: 0;
+}
+
+#stats em {
+  color: black;
+}
+
+#stats li {
+  display: inline-block;
+  margin: 0 5px;
+  list-style: none;
+  padding-top: 11px;
+}
+
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/mocha.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/mocha.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/mocha.js	(revision 533)
@@ -0,0 +1,4204 @@
+;(function(){
+
+
+// CommonJS require()
+
+function require(p){
+    var path = require.resolve(p)
+      , mod = require.modules[path];
+    if (!mod) throw new Error('failed to require "' + p + '"');
+    if (!mod.exports) {
+      mod.exports = {};
+      mod.call(mod.exports, mod, mod.exports, require.relative(path));
+    }
+    return mod.exports;
+  }
+
+require.modules = {};
+
+require.resolve = function (path){
+    var orig = path
+      , reg = path + '.js'
+      , index = path + '/index.js';
+    return require.modules[reg] && reg
+      || require.modules[index] && index
+      || orig;
+  };
+
+require.register = function (path, fn){
+    require.modules[path] = fn;
+  };
+
+require.relative = function (parent) {
+    return function(p){
+      if ('.' != p.charAt(0)) return require(p);
+      
+      var path = parent.split('/')
+        , segs = p.split('/');
+      path.pop();
+      
+      for (var i = 0; i < segs.length; i++) {
+        var seg = segs[i];
+        if ('..' == seg) path.pop();
+        else if ('.' != seg) path.push(seg);
+      }
+
+      return require(path.join('/'));
+    };
+  };
+
+
+require.register("browser/debug.js", function(module, exports, require){
+
+module.exports = function(type){
+  return function(){
+    
+  }
+};
+}); // module: browser/debug.js
+
+require.register("browser/diff.js", function(module, exports, require){
+
+}); // module: browser/diff.js
+
+require.register("browser/events.js", function(module, exports, require){
+
+/**
+ * Module exports.
+ */
+
+exports.EventEmitter = EventEmitter;
+
+/**
+ * Check if `obj` is an array.
+ */
+
+function isArray(obj) {
+  return '[object Array]' == {}.toString.call(obj);
+}
+
+/**
+ * Event emitter constructor.
+ *
+ * @api public.
+ */
+
+function EventEmitter(){};
+
+/**
+ * Adds a listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.on = function (name, fn) {
+  if (!this.$events) {
+    this.$events = {};
+  }
+
+  if (!this.$events[name]) {
+    this.$events[name] = fn;
+  } else if (isArray(this.$events[name])) {
+    this.$events[name].push(fn);
+  } else {
+    this.$events[name] = [this.$events[name], fn];
+  }
+
+  return this;
+};
+
+EventEmitter.prototype.addListener = EventEmitter.prototype.on;
+
+/**
+ * Adds a volatile listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.once = function (name, fn) {
+  var self = this;
+
+  function on () {
+    self.removeListener(name, on);
+    fn.apply(this, arguments);
+  };
+
+  on.listener = fn;
+  this.on(name, on);
+
+  return this;
+};
+
+/**
+ * Removes a listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.removeListener = function (name, fn) {
+  if (this.$events && this.$events[name]) {
+    var list = this.$events[name];
+
+    if (isArray(list)) {
+      var pos = -1;
+
+      for (var i = 0, l = list.length; i < l; i++) {
+        if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
+          pos = i;
+          break;
+        }
+      }
+
+      if (pos < 0) {
+        return this;
+      }
+
+      list.splice(pos, 1);
+
+      if (!list.length) {
+        delete this.$events[name];
+      }
+    } else if (list === fn || (list.listener && list.listener === fn)) {
+      delete this.$events[name];
+    }
+  }
+
+  return this;
+};
+
+/**
+ * Removes all listeners for an event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.removeAllListeners = function (name) {
+  if (name === undefined) {
+    this.$events = {};
+    return this;
+  }
+
+  if (this.$events && this.$events[name]) {
+    this.$events[name] = null;
+  }
+
+  return this;
+};
+
+/**
+ * Gets all listeners for a certain event.
+ *
+ * @api publci
+ */
+
+EventEmitter.prototype.listeners = function (name) {
+  if (!this.$events) {
+    this.$events = {};
+  }
+
+  if (!this.$events[name]) {
+    this.$events[name] = [];
+  }
+
+  if (!isArray(this.$events[name])) {
+    this.$events[name] = [this.$events[name]];
+  }
+
+  return this.$events[name];
+};
+
+/**
+ * Emits an event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.emit = function (name) {
+  if (!this.$events) {
+    return false;
+  }
+
+  var handler = this.$events[name];
+
+  if (!handler) {
+    return false;
+  }
+
+  var args = [].slice.call(arguments, 1);
+
+  if ('function' == typeof handler) {
+    handler.apply(this, args);
+  } else if (isArray(handler)) {
+    var listeners = handler.slice();
+
+    for (var i = 0, l = listeners.length; i < l; i++) {
+      listeners[i].apply(this, args);
+    }
+  } else {
+    return false;
+  }
+
+  return true;
+};
+}); // module: browser/events.js
+
+require.register("browser/fs.js", function(module, exports, require){
+
+}); // module: browser/fs.js
+
+require.register("browser/path.js", function(module, exports, require){
+
+}); // module: browser/path.js
+
+require.register("browser/progress.js", function(module, exports, require){
+
+/**
+ * Expose `Progress`.
+ */
+
+module.exports = Progress;
+
+/**
+ * Initialize a new `Progress` indicator.
+ */
+
+function Progress() {
+  this.percent = 0;
+  this.size(0);
+  this.fontSize(11);
+  this.font('helvetica, arial, sans-serif');
+}
+
+/**
+ * Set progress size to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.size = function(n){
+  this._size = n;
+  return this;
+};
+
+/**
+ * Set text to `str`.
+ *
+ * @param {String} str
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.text = function(str){
+  this._text = str;
+  return this;
+};
+
+/**
+ * Set font size to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.fontSize = function(n){
+  this._fontSize = n;
+  return this;
+};
+
+/**
+ * Set font `family`.
+ *
+ * @param {String} family
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.font = function(family){
+  this._font = family;
+  return this;
+};
+
+/**
+ * Update percentage to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.update = function(n){
+  this.percent = n;
+  return this;
+};
+
+/**
+ * Draw on `ctx`.
+ *
+ * @param {CanvasRenderingContext2d} ctx
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.draw = function(ctx){
+  var percent = Math.min(this.percent, 100)
+    , size = this._size
+    , half = size / 2
+    , x = half
+    , y = half
+    , rad = half - 1
+    , fontSize = this._fontSize;
+
+  ctx.font = fontSize + 'px ' + this._font;
+
+  var angle = Math.PI * 2 * (percent / 100);
+  ctx.clearRect(0, 0, size, size);
+
+  // outer circle
+  ctx.strokeStyle = '#9f9f9f';
+  ctx.beginPath();
+  ctx.arc(x, y, rad, 0, angle, false);
+  ctx.stroke();
+
+  // inner circle
+  ctx.strokeStyle = '#eee';
+  ctx.beginPath();
+  ctx.arc(x, y, rad - 1, 0, angle, true);
+  ctx.stroke();
+
+  // text
+  var text = this._text || (percent | 0) + '%'
+    , w = ctx.measureText(text).width;
+
+  ctx.fillText(
+      text
+    , x - w / 2 + 1
+    , y + fontSize / 2 - 1);
+
+  return this;
+};
+
+}); // module: browser/progress.js
+
+require.register("browser/tty.js", function(module, exports, require){
+
+exports.isatty = function(){
+  return true;
+};
+
+exports.getWindowSize = function(){
+  return [window.innerHeight, window.innerWidth];
+};
+}); // module: browser/tty.js
+
+require.register("context.js", function(module, exports, require){
+
+/**
+ * Expose `Context`.
+ */
+
+module.exports = Context;
+
+/**
+ * Initialize a new `Context`.
+ *
+ * @api private
+ */
+
+function Context(){}
+
+/**
+ * Set the context `Runnable` to `runnable`.
+ *
+ * @param {Runnable} runnable
+ * @return {Context}
+ * @api private
+ */
+
+Context.prototype.runnable = function(runnable){
+  this._runnable = runnable;
+  return this;
+};
+
+/**
+ * Set test timeout `ms`.
+ *
+ * @param {Number} ms
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.timeout = function(ms){
+  this._runnable.timeout(ms);
+  return this;
+};
+
+/**
+ * Inspect the context void of `._runnable`.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Context.prototype.inspect = function(){
+  return JSON.stringify(this, function(key, val){
+    return '_runnable' == key
+      ? undefined
+      : val;
+  }, 2);
+};
+
+}); // module: context.js
+
+require.register("hook.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Runnable = require('./runnable');
+
+/**
+ * Expose `Hook`.
+ */
+
+module.exports = Hook;
+
+/**
+ * Initialize a new `Hook` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Hook(title, fn) {
+  Runnable.call(this, title, fn);
+  this.type = 'hook';
+}
+
+/**
+ * Inherit from `Runnable.prototype`.
+ */
+
+Hook.prototype = new Runnable;
+Hook.prototype.constructor = Hook;
+
+
+}); // module: hook.js
+
+require.register("interfaces/bdd.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test');
+
+/**
+ * BDD-style interface:
+ * 
+ *      describe('Array', function(){
+ *        describe('#indexOf()', function(){
+ *          it('should return -1 when not present', function(){
+ *
+ *          });
+ *
+ *          it('should return the index when present', function(){
+ *
+ *          });
+ *        });
+ *      });
+ * 
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('pre-require', function(context){
+
+    // noop variants
+
+    context.xdescribe = function(){};
+    context.xit = function(){};
+
+    /**
+     * Execute before running tests.
+     */
+
+    context.before = function(fn){
+      suites[0].beforeAll(fn);
+    };
+
+    /**
+     * Execute after running tests.
+     */
+
+    context.after = function(fn){
+      suites[0].afterAll(fn);
+    };
+
+    /**
+     * Execute before each test case.
+     */
+
+    context.beforeEach = function(fn){
+      suites[0].beforeEach(fn);
+    };
+
+    /**
+     * Execute after each test case.
+     */
+
+    context.afterEach = function(fn){
+      suites[0].afterEach(fn);
+    };
+
+    /**
+     * Describe a "suite" with the given `title`
+     * and callback `fn` containing nested suites
+     * and/or tests.
+     */
+  
+    context.describe = function(title, fn){
+      var suite = Suite.create(suites[0], title);
+      suites.unshift(suite);
+      fn();
+      suites.shift();
+    };
+
+    /**
+     * Describe a specification or test-case
+     * with the given `title` and callback `fn`
+     * acting as a thunk.
+     */
+
+    context.it = function(title, fn){
+      suites[0].addTest(new Test(title, fn));
+    };
+  });
+};
+
+}); // module: interfaces/bdd.js
+
+require.register("interfaces/exports.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test');
+
+/**
+ * TDD-style interface:
+ * 
+ *     exports.Array = {
+ *       '#indexOf()': {
+ *         'should return -1 when the value is not present': function(){
+ *           
+ *         },
+ *
+ *         'should return the correct index when the value is present': function(){
+ *           
+ *         }
+ *       }
+ *     };
+ * 
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('require', visit);
+
+  function visit(obj) {
+    var suite;
+    for (var key in obj) {
+      if ('function' == typeof obj[key]) {
+        var fn = obj[key];
+        switch (key) {
+          case 'before':
+            suites[0].beforeAll(fn);
+            break;
+          case 'after':
+            suites[0].afterAll(fn);
+            break;
+          case 'beforeEach':
+            suites[0].beforeEach(fn);
+            break;
+          case 'afterEach':
+            suites[0].afterEach(fn);
+            break;
+          default:
+            suites[0].addTest(new Test(key, fn));
+        }
+      } else {
+        var suite = Suite.create(suites[0], key);
+        suites.unshift(suite);
+        visit(obj[key]);
+        suites.shift();
+      }
+    }
+  }
+};
+}); // module: interfaces/exports.js
+
+require.register("interfaces/index.js", function(module, exports, require){
+
+exports.bdd = require('./bdd');
+exports.tdd = require('./tdd');
+exports.qunit = require('./qunit');
+exports.exports = require('./exports');
+
+}); // module: interfaces/index.js
+
+require.register("interfaces/qunit.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test');
+
+/**
+ * QUnit-style interface:
+ * 
+ *     suite('Array');
+ *     
+ *     test('#length', function(){
+ *       var arr = [1,2,3];
+ *       ok(arr.length == 3);
+ *     });
+ *     
+ *     test('#indexOf()', function(){
+ *       var arr = [1,2,3];
+ *       ok(arr.indexOf(1) == 0);
+ *       ok(arr.indexOf(2) == 1);
+ *       ok(arr.indexOf(3) == 2);
+ *     });
+ *     
+ *     suite('String');
+ *     
+ *     test('#length', function(){
+ *       ok('foo'.length == 3);
+ *     });
+ * 
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('pre-require', function(context){
+
+    /**
+     * Execute before running tests.
+     */
+
+    context.before = function(fn){
+      suites[0].beforeAll(fn);
+    };
+
+    /**
+     * Execute after running tests.
+     */
+
+    context.after = function(fn){
+      suites[0].afterAll(fn);
+    };
+
+    /**
+     * Execute before each test case.
+     */
+
+    context.beforeEach = function(fn){
+      suites[0].beforeEach(fn);
+    };
+
+    /**
+     * Execute after each test case.
+     */
+
+    context.afterEach = function(fn){
+      suites[0].afterEach(fn);
+    };
+
+    /**
+     * Describe a "suite" with the given `title`.
+     */
+  
+    context.suite = function(title){
+      if (suites.length > 1) suites.shift();
+      var suite = Suite.create(suites[0], title);
+      suites.unshift(suite);
+    };
+
+    /**
+     * Describe a specification or test-case
+     * with the given `title` and callback `fn`
+     * acting as a thunk.
+     */
+
+    context.test = function(title, fn){
+      suites[0].addTest(new Test(title, fn));
+    };
+  });
+};
+
+}); // module: interfaces/qunit.js
+
+require.register("interfaces/tdd.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+  , Test = require('../test');
+
+/**
+ * TDD-style interface:
+ *
+ *      suite('Array', function(){
+ *        suite('#indexOf()', function(){
+ *          suiteSetup(function(){
+ *
+ *          });
+ *          
+ *          test('should return -1 when not present', function(){
+ *
+ *          });
+ *
+ *          test('should return the index when present', function(){
+ *
+ *          });
+ *
+ *          suiteTeardown(function(){
+ *
+ *          });
+ *        });
+ *      });
+ *
+ */
+
+module.exports = function(suite){
+  var suites = [suite];
+
+  suite.on('pre-require', function(context){
+
+    /**
+     * Execute before each test case.
+     */
+
+    context.setup = function(fn){
+      suites[0].beforeEach(fn);
+    };
+
+    /**
+     * Execute after each test case.
+     */
+
+    context.teardown = function(fn){
+      suites[0].afterEach(fn);
+    };
+
+    /**
+     * Execute before the suite.
+     */
+
+    context.suiteSetup = function(fn){
+      suites[0].beforeAll(fn);
+    };
+
+    /**
+     * Execute after the suite.
+     */
+
+    context.suiteTeardown = function(fn){
+      suites[0].afterAll(fn);
+    };
+
+    /**
+     * Describe a "suite" with the given `title`
+     * and callback `fn` containing nested suites
+     * and/or tests.
+     */
+
+    context.suite = function(title, fn){
+      var suite = Suite.create(suites[0], title);
+      suites.unshift(suite);
+      fn();
+      suites.shift();
+    };
+
+    /**
+     * Describe a specification or test-case
+     * with the given `title` and callback `fn`
+     * acting as a thunk.
+     */
+
+    context.test = function(title, fn){
+      suites[0].addTest(new Test(title, fn));
+    };
+  });
+};
+
+}); // module: interfaces/tdd.js
+
+require.register("mocha.js", function(module, exports, require){
+
+/*!
+ * mocha
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('browser/path');
+
+/**
+ * Expose `Mocha`.
+ */
+
+exports = module.exports = Mocha;
+
+/**
+ * Library version.
+ */
+
+exports.version = '1.0.3';
+
+/**
+ * Expose internals.
+ */
+
+exports.utils = require('./utils');
+exports.interfaces = require('./interfaces');
+exports.reporters = require('./reporters');
+exports.Runnable = require('./runnable');
+exports.Context = require('./context');
+exports.Runner = require('./runner');
+exports.Suite = require('./suite');
+exports.Hook = require('./hook');
+exports.Test = require('./test');
+
+/**
+ * Return image `name` path.
+ *
+ * @param {String} name
+ * @return {String}
+ * @api private
+ */
+
+function image(name) {
+  return __dirname + '/../images/' + name + '.png';
+}
+
+/**
+ * Setup mocha with `options`.
+ *
+ * Options:
+ *
+ *   - `ui` name "bdd", "tdd", "exports" etc
+ *   - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
+ *   - `globals` array of accepted globals
+ *   - `timeout` timeout in milliseconds
+ *   - `ignoreLeaks` ignore global leaks
+ *   - `grep` string or regexp to filter tests with
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+function Mocha(options) {
+  options = options || {};
+  options.grep = 'string' == typeof options.grep
+    ? new RegExp(options.grep)
+    : options.grep;
+  this.files = [];
+  this.options = options;
+  this.suite = new exports.Suite('', new exports.Context);
+  this.ui(options.ui);
+  this.reporter(options.reporter);
+  if (options.timeout) this.suite.timeout(options.timeout);
+}
+
+/**
+ * Add test `file`.
+ *
+ * @param {String} file
+ * @api public
+ */
+
+Mocha.prototype.addFile = function(file){
+  this.files.push(file);
+  return this;
+};
+
+/**
+ * Set reporter to `name`, defaults to "dot".
+ *
+ * @param {String} name
+ * @api public
+ */
+
+Mocha.prototype.reporter = function(name){
+  name = name || 'dot';
+  this._reporter = require('./reporters/' + name);
+  if (!this._reporter) throw new Error('invalid reporter "' + name + '"');
+  return this;
+};
+
+/**
+ * Set test UI `name`, defaults to "bdd".
+ *
+ * @param {String} bdd
+ * @api public
+ */
+
+Mocha.prototype.ui = function(name){
+  name = name || 'bdd';
+  this._ui = exports.interfaces[name];
+  if (!this._ui) throw new Error('invalid interface "' + name + '"');
+  this._ui = this._ui(this.suite);
+  return this;
+};
+
+/**
+ * Load registered files.
+ *
+ * @api private
+ */
+
+Mocha.prototype.loadFiles = function(){
+  var suite = this.suite;
+  this.files.forEach(function(file){
+    file = path.resolve(file);
+    suite.emit('pre-require', global, file);
+    suite.emit('require', require(file), file);
+    suite.emit('post-require', global, file);
+  });
+};
+
+/**
+ * Enable growl support.
+ *
+ * @api private
+ */
+
+Mocha.prototype.growl = function(runner, reporter) {
+  var notify = require('growl');
+
+  runner.on('end', function(){
+    var stats = reporter.stats;
+    if (stats.failures) {
+      var msg = stats.failures + ' of ' + runner.total + ' tests failed';
+      notify(msg, { title: 'Failed', image: image('fail') });
+    } else {
+      notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
+          title: 'Passed'
+        , image: image('pass')
+      });
+    }
+  });
+};
+
+/**
+ * Add regexp to grep for to the options object
+ *
+ * @param {RegExp} or {String} re
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.grep = function(re){
+  this.options.grep = 'string' == typeof re
+    ? new RegExp(re)
+    : re;
+  return this;
+};
+
+/**
+ * Run tests and invoke `fn()` when complete.
+ *
+ * @param {Function} fn
+ * @return {Runner}
+ * @api public
+ */
+
+Mocha.prototype.run = function(fn){
+  this.loadFiles();
+  var suite = this.suite;
+  var options = this.options;
+  var runner = new exports.Runner(suite);
+  var reporter = new this._reporter(runner);
+  runner.ignoreLeaks = options.ignoreLeaks;
+  if (options.grep) runner.grep(options.grep);
+  if (options.globals) runner.globals(options.globals);
+  if (options.growl) this.growl(runner, reporter);
+  return runner.run(fn);
+};
+
+}); // module: mocha.js
+
+require.register("reporters/base.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var tty = require('browser/tty')
+  , diff = require('browser/diff');
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Check if both stdio streams are associated with a tty.
+ */
+
+var isatty = tty.isatty(1) && tty.isatty(2);
+
+/**
+ * Expose `Base`.
+ */
+
+exports = module.exports = Base;
+
+/**
+ * Enable coloring by default.
+ */
+
+exports.useColors = isatty;
+
+/**
+ * Default color map.
+ */
+
+exports.colors = {
+    'pass': 90
+  , 'fail': 31
+  , 'bright pass': 92
+  , 'bright fail': 91
+  , 'bright yellow': 93
+  , 'pending': 36
+  , 'suite': 0
+  , 'error title': 0
+  , 'error message': 31
+  , 'error stack': 90
+  , 'checkmark': 32
+  , 'fast': 90
+  , 'medium': 33
+  , 'slow': 31
+  , 'green': 32
+  , 'light': 90
+  , 'diff gutter': 90
+  , 'diff added': 42
+  , 'diff removed': 41
+};
+
+/**
+ * Color `str` with the given `type`,
+ * allowing colors to be disabled,
+ * as well as user-defined color
+ * schemes.
+ *
+ * @param {String} type
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+var color = exports.color = function(type, str) {
+  if (!exports.useColors) return str;
+  return '\033[' + exports.colors[type] + 'm' + str + '\033[0m';
+};
+
+/**
+ * Expose term window size, with some
+ * defaults for when stderr is not a tty.
+ */
+
+exports.window = {
+  width: isatty
+    ? process.stdout.getWindowSize
+      ? process.stdout.getWindowSize(1)[0]
+      : tty.getWindowSize()[1]
+    : 75
+};
+
+/**
+ * Expose some basic cursor interactions
+ * that are common among reporters.
+ */
+
+exports.cursor = {
+  hide: function(){
+    process.stdout.write('\033[?25l');
+  },
+
+  show: function(){
+    process.stdout.write('\033[?25h');
+  },
+
+  deleteLine: function(){
+    process.stdout.write('\033[2K');
+  },
+
+  beginningOfLine: function(){
+    process.stdout.write('\033[0G');
+  },
+
+  CR: function(){
+    exports.cursor.deleteLine();
+    exports.cursor.beginningOfLine();
+  }
+};
+
+/**
+ * A test is considered slow if it
+ * exceeds the following value in milliseconds.
+ */
+
+exports.slow = 75;
+
+/**
+ * Outut the given `failures` as a list.
+ *
+ * @param {Array} failures
+ * @api public
+ */
+
+exports.list = function(failures){
+  console.error();
+  failures.forEach(function(test, i){
+    // format
+    var fmt = color('error title', '  %s) %s:\n')
+      + color('error message', '     %s')
+      + color('error stack', '\n%s\n');
+
+    // msg
+    var err = test.err
+      , message = err.message || ''
+      , stack = err.stack || message
+      , index = stack.indexOf(message) + message.length
+      , msg = stack.slice(0, index)
+      , actual = err.actual
+      , expected = err.expected;
+
+    // actual / expected diff
+    if ('string' == typeof actual && 'string' == typeof expected) {
+      var len = Math.max(actual.length, expected.length);
+
+      if (len < 20) msg = errorDiff(err, 'Chars');
+      else msg = errorDiff(err, 'Words');
+
+      // linenos
+      var lines = msg.split('\n');
+      if (lines.length > 4) {
+        var width = String(lines.length).length;
+        msg = lines.map(function(str, i){
+          return pad(++i, width) + ' |' + ' ' + str;
+        }).join('\n');
+      }
+
+      // legend
+      msg = '\n'
+        + color('diff removed', 'actual')
+        + ' '
+        + color('diff added', 'expected')
+        + '\n\n'
+        + msg
+        + '\n';
+
+      // indent
+      msg = msg.replace(/^/gm, '      ');
+
+      fmt = color('error title', '  %s) %s:\n%s')
+        + color('error stack', '\n%s\n');
+    }
+
+    // indent stack trace without msg
+    stack = stack.slice(index ? index + 1 : index)
+      .replace(/^/gm, '  ');
+
+    console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
+  });
+};
+
+/**
+ * Initialize a new `Base` reporter.
+ *
+ * All other reporters generally
+ * inherit from this reporter, providing
+ * stats such as test duration, number
+ * of tests passed / failed etc.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Base(runner) {
+  var self = this
+    , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
+    , failures = this.failures = [];
+
+  if (!runner) return;
+  this.runner = runner;
+
+  runner.on('start', function(){
+    stats.start = new Date;
+  });
+
+  runner.on('suite', function(suite){
+    stats.suites = stats.suites || 0;
+    suite.root || stats.suites++;
+  });
+
+  runner.on('test end', function(test){
+    stats.tests = stats.tests || 0;
+    stats.tests++;
+  });
+
+  runner.on('pass', function(test){
+    stats.passes = stats.passes || 0;
+
+    var medium = exports.slow / 2;
+    test.speed = test.duration > exports.slow
+      ? 'slow'
+      : test.duration > medium
+        ? 'medium'
+        : 'fast';
+
+    stats.passes++;
+  });
+
+  runner.on('fail', function(test, err){
+    stats.failures = stats.failures || 0;
+    stats.failures++;
+    test.err = err;
+    failures.push(test);
+  });
+
+  runner.on('end', function(){
+    stats.end = new Date;
+    stats.duration = new Date - stats.start;
+  });
+
+  runner.on('pending', function(){
+    stats.pending++;
+  });
+}
+
+/**
+ * Output common epilogue used by many of
+ * the bundled reporters.
+ *
+ * @api public
+ */
+
+Base.prototype.epilogue = function(){
+  var stats = this.stats
+    , fmt
+    , tests;
+
+  console.log();
+
+  function pluralize(n) {
+    return 1 == n ? 'test' : 'tests';
+  }
+
+  // failure
+  if (stats.failures) {
+    fmt = color('bright fail', '  â')
+      + color('fail', ' %d of %d %s failed')
+      + color('light', ':')
+
+    console.error(fmt,
+      stats.failures,
+      this.runner.total,
+      pluralize(this.runner.total));
+
+    Base.list(this.failures);
+    console.error();
+    return;
+  }
+
+  // pass
+  fmt = color('bright pass', '  â')
+    + color('green', ' %d %s complete')
+    + color('light', ' (%dms)');
+
+  console.log(fmt,
+    stats.tests || 0,
+    pluralize(stats.tests),
+    stats.duration);
+
+  // pending
+  if (stats.pending) {
+    fmt = color('pending', '  â¢')
+      + color('pending', ' %d %s pending');
+
+    console.log(fmt, stats.pending, pluralize(stats.pending));
+  }
+
+  console.log();
+};
+
+/**
+ * Pad the given `str` to `len`.
+ *
+ * @param {String} str
+ * @param {String} len
+ * @return {String}
+ * @api private
+ */
+
+function pad(str, len) {
+  str = String(str);
+  return Array(len - str.length + 1).join(' ') + str;
+}
+
+/**
+ * Return a character diff for `err`.
+ *
+ * @param {Error} err
+ * @return {String}
+ * @api private
+ */
+
+function errorDiff(err, type) {
+  return diff['diff' + type](err.actual, err.expected).map(function(str){
+    if (/^(\n+)$/.test(str.value)) str.value = Array(++RegExp.$1.length).join('<newline>');
+    if (str.added) return colorLines('diff added', str.value);
+    if (str.removed) return colorLines('diff removed', str.value);
+    return str.value;
+  }).join('');
+}
+
+/**
+ * Color lines for `str`, using the color `name`.
+ *
+ * @param {String} name
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function colorLines(name, str) {
+  return str.split('\n').map(function(str){
+    return color(name, str);
+  }).join('\n');
+}
+
+}); // module: reporters/base.js
+
+require.register("reporters/doc.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils');
+
+/**
+ * Expose `Doc`.
+ */
+
+exports = module.exports = Doc;
+
+/**
+ * Initialize a new `Doc` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Doc(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total
+    , indents = 2;
+
+  function indent() {
+    return Array(indents).join('  ');
+  }
+
+  runner.on('suite', function(suite){
+    if (suite.root) return;
+    ++indents;
+    console.log('%s<section class="suite">', indent());
+    ++indents;
+    console.log('%s<h1>%s</h1>', indent(), suite.title);
+    console.log('%s<dl>', indent());
+  });
+
+  runner.on('suite end', function(suite){
+    if (suite.root) return;
+    console.log('%s</dl>', indent());
+    --indents;
+    console.log('%s</section>', indent());
+    --indents;
+  });
+
+  runner.on('pass', function(test){
+    console.log('%s  <dt>%s</dt>', indent(), test.title);
+    var code = utils.escape(clean(test.fn.toString()));
+    console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);
+  });
+}
+
+/**
+ * Strip the function definition from `str`,
+ * and re-indent for pre whitespace.
+ */
+
+function clean(str) {
+  str = str
+    .replace(/^function *\(.*\) *{/, '')
+    .replace(/\s+\}$/, '');
+
+  var spaces = str.match(/^\n?( *)/)[1].length
+    , re = new RegExp('^ {' + spaces + '}', 'gm');
+
+  str = str.replace(re, '');
+
+  return str;
+}
+}); // module: reporters/doc.js
+
+require.register("reporters/dot.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , color = Base.color;
+
+/**
+ * Expose `Dot`.
+ */
+
+exports = module.exports = Dot;
+
+/**
+ * Initialize a new `Dot` matrix test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Dot(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , width = Base.window.width * .75 | 0
+    , n = 0;
+
+  runner.on('start', function(){
+    process.stdout.write('\n  ');
+  });
+
+  runner.on('pending', function(test){
+    process.stdout.write(color('pending', '.'));
+  });
+
+  runner.on('pass', function(test){
+    if (++n % width == 0) process.stdout.write('\n  ');
+    if ('slow' == test.speed) {
+      process.stdout.write(color('bright yellow', '.'));
+    } else {
+      process.stdout.write(color(test.speed, '.'));
+    }
+  });
+
+  runner.on('fail', function(test, err){
+    if (++n % width == 0) process.stdout.write('\n  ');
+    process.stdout.write(color('fail', '.'));
+  });
+
+  runner.on('end', function(){
+    console.log();
+    self.epilogue();
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+Dot.prototype = new Base;
+Dot.prototype.constructor = Dot;
+
+}); // module: reporters/dot.js
+
+require.register("reporters/html-cov.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var JSONCov = require('./json-cov')
+  , fs = require('browser/fs');
+
+/**
+ * Expose `HTMLCov`.
+ */
+
+exports = module.exports = HTMLCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTMLCov(runner) {
+  var jade = require('jade')
+    , file = __dirname + '/templates/coverage.jade'
+    , str = fs.readFileSync(file, 'utf8')
+    , fn = jade.compile(str, { filename: file })
+    , self = this;
+
+  JSONCov.call(this, runner, false);
+
+  runner.on('end', function(){
+    process.stdout.write(fn({
+        cov: self.cov
+      , coverageClass: coverageClass
+    }));
+  });
+}
+
+function coverageClass(n) {
+  if (n >= 75) return 'high';
+  if (n >= 50) return 'medium';
+  if (n >= 25) return 'low';
+  return 'terrible';
+}
+}); // module: reporters/html-cov.js
+
+require.register("reporters/html.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils')
+  , Progress = require('../browser/progress')
+  , escape = utils.escape;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Expose `Doc`.
+ */
+
+exports = module.exports = HTML;
+
+/**
+ * Stats template.
+ */
+
+var statsTemplate = '<ul id="stats">'
+  + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
+  + '<li class="passes">passes: <em>0</em></li>'
+  + '<li class="failures">failures: <em>0</em></li>'
+  + '<li class="duration">duration: <em>0</em>s</li>'
+  + '</ul>';
+
+/**
+ * Initialize a new `Doc` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTML(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total
+    , root = document.getElementById('mocha')
+    , stat = fragment(statsTemplate)
+    , items = stat.getElementsByTagName('li')
+    , passes = items[1].getElementsByTagName('em')[0]
+    , failures = items[2].getElementsByTagName('em')[0]
+    , duration = items[3].getElementsByTagName('em')[0]
+    , canvas = stat.getElementsByTagName('canvas')[0]
+    , stack = [root]
+    , progress
+    , ctx
+
+  if (canvas.getContext) {
+    ctx = canvas.getContext('2d');
+    progress = new Progress;
+  }
+
+  if (!root) return error('#mocha div missing, add it to your document');
+
+  root.appendChild(stat);
+
+  if (progress) progress.size(40);
+
+  runner.on('suite', function(suite){
+    if (suite.root) return;
+
+    // suite
+    var el = fragment('<div class="suite"><h1>%s</h1></div>', suite.title);
+
+    // container
+    stack[0].appendChild(el);
+    stack.unshift(document.createElement('div'));
+    el.appendChild(stack[0]);
+  });
+
+  runner.on('suite end', function(suite){
+    if (suite.root) return;
+    stack.shift();
+  });
+
+  runner.on('fail', function(test, err){
+    if ('hook' == test.type || err.uncaught) runner.emit('test end', test);
+  });
+
+  runner.on('test end', function(test){
+    // TODO: add to stats
+    var percent = stats.tests / total * 100 | 0;
+    if (progress) progress.update(percent).draw(ctx);
+
+    // update stats
+    var ms = new Date - stats.start;
+    text(passes, stats.passes);
+    text(failures, stats.failures);
+    text(duration, (ms / 1000).toFixed(2));
+
+    // test
+    if ('passed' == test.state) {
+      var el = fragment('<div class="test pass %e"><h2>%e<span class="duration">%ems</span></h2></div>', test.speed, test.title, test.duration);
+    } else if (test.pending) {
+      var el = fragment('<div class="test pass pending"><h2>%e</h2></div>', test.title);
+    } else {
+      var el = fragment('<div class="test fail"><h2>%e</h2></div>', test.title);
+      var str = test.err.stack || test.err.toString();
+
+      // FF / Opera do not add the message
+      if (!~str.indexOf(test.err.message)) {
+        str = test.err.message + '\n' + str;
+      }
+
+      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
+      // check for the result of the stringifying.
+      if ('[object Error]' == str) str = test.err.message;
+
+      // Safari doesn't give you a stack. Let's at least provide a source line.
+      if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
+        str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
+      }
+
+      el.appendChild(fragment('<pre class="error">%e</pre>', str));
+    }
+
+    // toggle code
+    var h2 = el.getElementsByTagName('h2')[0];
+
+    on(h2, 'click', function(){
+      pre.style.display = 'none' == pre.style.display
+        ? 'block'
+        : 'none';
+    });
+
+    // code
+    // TODO: defer
+    if (!test.pending) {
+      var pre = fragment('<pre><code>%e</code></pre>', clean(test.fn.toString()));
+      el.appendChild(pre);
+      pre.style.display = 'none';
+    }
+
+    stack[0].appendChild(el);
+  });
+}
+
+/**
+ * Display error `msg`.
+ */
+
+function error(msg) {
+  document.body.appendChild(fragment('<div id="error">%s</div>', msg));
+}
+
+/**
+ * Return a DOM fragment from `html`.
+ */
+
+function fragment(html) {
+  var args = arguments
+    , div = document.createElement('div')
+    , i = 1;
+
+  div.innerHTML = html.replace(/%([se])/g, function(_, type){
+    switch (type) {
+      case 's': return String(args[i++]);
+      case 'e': return escape(args[i++]);
+    }
+  });
+
+  return div.firstChild;
+}
+
+/**
+ * Set `el` text to `str`.
+ */
+
+function text(el, str) {
+  if (el.textContent) {
+    el.textContent = str;
+  } else {
+    el.innerText = str;
+  }
+}
+
+/**
+ * Listen on `event` with callback `fn`.
+ */
+
+function on(el, event, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(event, fn, false);
+  } else {
+    el.attachEvent('on' + event, fn);
+  }
+}
+
+/**
+ * Strip the function definition from `str`,
+ * and re-indent for pre whitespace.
+ */
+
+function clean(str) {
+  str = str
+    .replace(/^function *\(.*\) *{/, '')
+    .replace(/\s+\}$/, '');
+
+  var spaces = str.match(/^\n?( *)/)[1].length
+    , re = new RegExp('^ {' + spaces + '}', 'gm');
+
+  str = str
+    .replace(re, '')
+    .replace(/^\s+/, '');
+
+  return str;
+}
+
+}); // module: reporters/html.js
+
+require.register("reporters/index.js", function(module, exports, require){
+
+exports.Base = require('./base');
+exports.Dot = require('./dot');
+exports.Doc = require('./doc');
+exports.TAP = require('./tap');
+exports.JSON = require('./json');
+exports.HTML = require('./html');
+exports.List = require('./list');
+exports.Min = require('./min');
+exports.Spec = require('./spec');
+exports.Progress = require('./progress');
+exports.Landing = require('./landing');
+exports.JSONCov = require('./json-cov');
+exports.HTMLCov = require('./html-cov');
+exports.JSONStream = require('./json-stream');
+exports.XUnit = require('./xunit')
+exports.Teamcity = require('./teamcity')
+
+}); // module: reporters/index.js
+
+require.register("reporters/json-cov.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `JSONCov`.
+ */
+
+exports = module.exports = JSONCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @param {Boolean} output
+ * @api public
+ */
+
+function JSONCov(runner, output) {
+  var self = this
+    , output = 1 == arguments.length ? true : output;
+
+  Base.call(this, runner);
+
+  var tests = []
+    , failures = []
+    , passes = [];
+
+  runner.on('test end', function(test){
+    tests.push(test);
+  });
+
+  runner.on('pass', function(test){
+    passes.push(test);
+  });
+
+  runner.on('fail', function(test){
+    failures.push(test);
+  });
+
+  runner.on('end', function(){
+    var cov = global._$jscoverage || {};
+    var result = self.cov = map(cov);
+    result.stats = self.stats;
+    result.tests = tests.map(clean);
+    result.failures = failures.map(clean);
+    result.passes = passes.map(clean);
+    if (!output) return;
+    process.stdout.write(JSON.stringify(result, null, 2 ));
+  });
+}
+
+/**
+ * Map jscoverage data to a JSON structure
+ * suitable for reporting.
+ *
+ * @param {Object} cov
+ * @return {Object}
+ * @api private
+ */
+
+function map(cov) {
+  var ret = {
+      instrumentation: 'node-jscoverage'
+    , sloc: 0
+    , hits: 0
+    , misses: 0
+    , coverage: 0
+    , files: []
+  };
+
+  for (var filename in cov) {
+    var data = coverage(filename, cov[filename]);
+    ret.files.push(data);
+    ret.hits += data.hits;
+    ret.misses += data.misses;
+    ret.sloc += data.sloc;
+  }
+
+  if (ret.sloc > 0) {
+    ret.coverage = (ret.hits / ret.sloc) * 100;
+  }
+
+  return ret;
+};
+
+/**
+ * Map jscoverage data for a single source file
+ * to a JSON structure suitable for reporting.
+ *
+ * @param {String} filename name of the source file
+ * @param {Object} data jscoverage coverage data
+ * @return {Object}
+ * @api private
+ */
+
+function coverage(filename, data) {
+  var ret = {
+    filename: filename,
+    coverage: 0,
+    hits: 0,
+    misses: 0,
+    sloc: 0,
+    source: {}
+  };
+
+  data.source.forEach(function(line, num){
+    num++;
+
+    if (data[num] === 0) {
+      ret.misses++;
+      ret.sloc++;
+    } else if (data[num] !== undefined) {
+      ret.hits++;
+      ret.sloc++;
+    }
+
+    ret.source[num] = {
+        source: line
+      , coverage: data[num] === undefined
+        ? ''
+        : data[num]
+    };
+  });
+
+  ret.coverage = ret.hits / ret.sloc * 100;
+
+  return ret;
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+  return {
+      title: test.title
+    , fullTitle: test.fullTitle()
+    , duration: test.duration
+  }
+}
+
+}); // module: reporters/json-cov.js
+
+require.register("reporters/json-stream.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , color = Base.color;
+
+/**
+ * Expose `List`.
+ */
+
+exports = module.exports = List;
+
+/**
+ * Initialize a new `List` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function List(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total;
+
+  runner.on('start', function(){
+    console.log(JSON.stringify(['start', { total: total }]));
+  });
+
+  runner.on('pass', function(test){
+    console.log(JSON.stringify(['pass', clean(test)]));
+  });
+
+  runner.on('fail', function(test, err){
+    console.log(JSON.stringify(['fail', clean(test)]));
+  });
+
+  runner.on('end', function(){
+    process.stdout.write(JSON.stringify(['end', self.stats]));
+  });
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+  return {
+      title: test.title
+    , fullTitle: test.fullTitle()
+    , duration: test.duration
+  }
+}
+}); // module: reporters/json-stream.js
+
+require.register("reporters/json.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `JSON`.
+ */
+
+exports = module.exports = JSONReporter;
+
+/**
+ * Initialize a new `JSON` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function JSONReporter(runner) {
+  var self = this;
+  Base.call(this, runner);
+
+  var tests = []
+    , failures = []
+    , passes = [];
+
+  runner.on('test end', function(test){
+    tests.push(test);
+  });
+
+  runner.on('pass', function(test){
+    passes.push(test);
+  });
+
+  runner.on('fail', function(test){
+    failures.push(test);
+  });
+
+  runner.on('end', function(){
+    var obj = {
+        stats: self.stats
+      , tests: tests.map(clean)
+      , failures: failures.map(clean)
+      , passes: passes.map(clean)
+    };
+
+    process.stdout.write(JSON.stringify(obj, null, 2));
+  });
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+  return {
+      title: test.title
+    , fullTitle: test.fullTitle()
+    , duration: test.duration
+  }
+}
+}); // module: reporters/json.js
+
+require.register("reporters/landing.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `Landing`.
+ */
+
+exports = module.exports = Landing;
+
+/**
+ * Airplane color.
+ */
+
+Base.colors.plane = 0;
+
+/**
+ * Airplane crash color.
+ */
+
+Base.colors['plane crash'] = 31;
+
+/**
+ * Runway color.
+ */
+
+Base.colors.runway = 90;
+
+/**
+ * Initialize a new `Landing` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Landing(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , width = Base.window.width * .75 | 0
+    , total = runner.total
+    , stream = process.stdout
+    , plane = color('plane', 'â')
+    , crashed = -1
+    , n = 0;
+
+  function runway() {
+    var buf = Array(width).join('-');
+    return '  ' + color('runway', buf);
+  }
+
+  runner.on('start', function(){
+    stream.write('\n  ');
+    cursor.hide();
+  });
+
+  runner.on('test end', function(test){
+    // check if the plane crashed
+    var col = -1 == crashed
+      ? width * ++n / total | 0
+      : crashed;
+
+    // show the crash
+    if ('failed' == test.state) {
+      plane = color('plane crash', 'â');
+      crashed = col;
+    }
+
+    // render landing strip
+    stream.write('\033[4F\n\n');
+    stream.write(runway());
+    stream.write('\n  ');
+    stream.write(color('runway', Array(col).join('â
+')));
+    stream.write(plane)
+    stream.write(color('runway', Array(width - col).join('â
+') + '\n'));
+    stream.write(runway());
+    stream.write('\033[0m');
+  });
+
+  runner.on('end', function(){
+    cursor.show();
+    console.log();
+    self.epilogue();
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+Landing.prototype = new Base;
+Landing.prototype.constructor = Landing;
+
+}); // module: reporters/landing.js
+
+require.register("reporters/list.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `List`.
+ */
+
+exports = module.exports = List;
+
+/**
+ * Initialize a new `List` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function List(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , n = 0;
+
+  runner.on('start', function(){
+    console.log();
+  });
+
+  runner.on('test', function(test){
+    process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));
+  });
+
+  runner.on('pending', function(test){
+    var fmt = color('checkmark', '  -')
+      + color('pending', ' %s');
+    console.log(fmt, test.fullTitle());
+  });
+
+  runner.on('pass', function(test){
+    var fmt = color('checkmark', '  â')
+      + color('pass', ' %s: ')
+      + color(test.speed, '%dms');
+    cursor.CR();
+    console.log(fmt, test.fullTitle(), test.duration);
+  });
+
+  runner.on('fail', function(test, err){
+    cursor.CR();
+    console.log(color('fail', '  %d) %s'), ++n, test.fullTitle());
+  });
+
+  runner.on('end', self.epilogue.bind(self));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+List.prototype = new Base;
+List.prototype.constructor = List;
+
+
+}); // module: reporters/list.js
+
+require.register("reporters/markdown.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils');
+
+/**
+ * Expose `Markdown`.
+ */
+
+exports = module.exports = Markdown;
+
+/**
+ * Initialize a new `Markdown` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Markdown(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total
+    , level = 0
+    , buf = '';
+
+  function title(str) {
+    return Array(level).join('#') + ' ' + str;
+  }
+
+  function indent() {
+    return Array(level).join('  ');
+  }
+
+  function mapTOC(suite, obj) {
+    var ret = obj;
+    obj = obj[suite.title] = obj[suite.title] || { suite: suite };
+    suite.suites.forEach(function(suite){
+      mapTOC(suite, obj);
+    });
+    return ret;
+  }
+
+  function stringifyTOC(obj, level) {
+    ++level;
+    var buf = '';
+    var link;
+    for (var key in obj) {
+      if ('suite' == key) continue;
+      if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
+      if (key) buf += Array(level).join('  ') + link;
+      buf += stringifyTOC(obj[key], level);
+    }
+    --level;
+    return buf;
+  }
+
+  function generateTOC(suite) {
+    var obj = mapTOC(suite, {});
+    return stringifyTOC(obj, 0);
+  }
+
+  generateTOC(runner.suite);
+
+  runner.on('suite', function(suite){
+    ++level;
+    var slug = utils.slug(suite.fullTitle());
+    buf += '<a name="' + slug + '" />' + '\n';
+    buf += title(suite.title) + '\n';
+  });
+
+  runner.on('suite end', function(suite){
+    --level;
+  });
+
+  runner.on('pass', function(test){
+    var code = clean(test.fn.toString());
+    buf += test.title + '.\n';
+    buf += '\n```js';
+    buf += code + '\n';
+    buf += '```\n\n';
+  });
+
+  runner.on('end', function(){
+    process.stdout.write('# TOC\n');
+    process.stdout.write(generateTOC(runner.suite));
+    process.stdout.write(buf);
+  });
+}
+
+/**
+ * Strip the function definition from `str`,
+ * and re-indent for pre whitespace.
+ */
+
+function clean(str) {
+  str = str
+    .replace(/^function *\(.*\) *{/, '')
+    .replace(/\s+\}$/, '');
+
+  var spaces = str.match(/^\n?( *)/)[1].length
+    , re = new RegExp('^ {' + spaces + '}', 'gm');
+
+  str = str.replace(re, '');
+
+  return str;
+}
+}); // module: reporters/markdown.js
+
+require.register("reporters/min.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Min`.
+ */
+
+exports = module.exports = Min;
+
+/**
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Min(runner) {
+  Base.call(this, runner);
+  
+  runner.on('start', function(){
+    // clear screen
+    process.stdout.write('\033[2J');
+    // set cursor position
+    process.stdout.write('\033[1;3H');
+  });
+
+  runner.on('end', this.epilogue.bind(this));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+Min.prototype = new Base;
+Min.prototype.constructor = Min;
+
+}); // module: reporters/min.js
+
+require.register("reporters/progress.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `Progress`.
+ */
+
+exports = module.exports = Progress;
+
+/**
+ * General progress bar color.
+ */
+
+Base.colors.progress = 90;
+
+/**
+ * Initialize a new `Progress` bar test reporter.
+ *
+ * @param {Runner} runner
+ * @param {Object} options
+ * @api public
+ */
+
+function Progress(runner, options) {
+  Base.call(this, runner);
+
+  var self = this
+    , options = options || {}
+    , stats = this.stats
+    , width = Base.window.width * .50 | 0
+    , total = runner.total
+    , complete = 0
+    , max = Math.max;
+
+  // default chars
+  options.open = options.open || '[';
+  options.complete = options.complete || 'â¬';
+  options.incomplete = options.incomplete || 'â
+';
+  options.close = options.close || ']';
+  options.verbose = false;
+
+  // tests started
+  runner.on('start', function(){
+    console.log();
+    cursor.hide();
+  });
+
+  // tests complete
+  runner.on('test end', function(){
+    complete++;
+    var incomplete = total - complete
+      , percent = complete / total
+      , n = width * percent | 0
+      , i = width - n;
+
+    cursor.CR();
+    process.stdout.write('\033[J');
+    process.stdout.write(color('progress', '  ' + options.open));
+    process.stdout.write(Array(n).join(options.complete));
+    process.stdout.write(Array(i).join(options.incomplete));
+    process.stdout.write(color('progress', options.close));
+    if (options.verbose) {
+      process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
+    }
+  });
+
+  // tests are complete, output some stats
+  // and the failures if any
+  runner.on('end', function(){
+    cursor.show();
+    console.log();
+    self.epilogue();
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+Progress.prototype = new Base;
+Progress.prototype.constructor = Progress;
+
+
+}); // module: reporters/progress.js
+
+require.register("reporters/spec.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `Spec`.
+ */
+
+exports = module.exports = Spec;
+
+/**
+ * Initialize a new `Spec` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Spec(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , indents = 0
+    , n = 0;
+
+  function indent() {
+    return Array(indents).join('  ')
+  }
+
+  runner.on('start', function(){
+    console.log();
+  });
+
+  runner.on('suite', function(suite){
+    ++indents;
+    console.log(color('suite', '%s%s'), indent(), suite.title);
+  });
+
+  runner.on('suite end', function(suite){
+    --indents;
+    if (1 == indents) console.log();
+  });
+
+  runner.on('test', function(test){
+    process.stdout.write(indent() + color('pass', '  âŠ ' + test.title + ': '));
+  });
+
+  runner.on('pending', function(test){
+    var fmt = indent() + color('pending', '  - %s');
+    console.log(fmt, test.title);
+  });
+
+  runner.on('pass', function(test){
+    if ('fast' == test.speed) {
+      var fmt = indent()
+        + color('checkmark', '  â')
+        + color('pass', ' %s ');
+      cursor.CR();
+      console.log(fmt, test.title);
+    } else {
+      var fmt = indent()
+        + color('checkmark', '  â')
+        + color('pass', ' %s ')
+        + color(test.speed, '(%dms)');
+      cursor.CR();
+      console.log(fmt, test.title, test.duration);
+    }
+  });
+
+  runner.on('fail', function(test, err){
+    cursor.CR();
+    console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);
+  });
+
+  runner.on('end', self.epilogue.bind(self));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+Spec.prototype = new Base;
+Spec.prototype.constructor = Spec;
+
+
+}); // module: reporters/spec.js
+
+require.register("reporters/tap.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , cursor = Base.cursor
+  , color = Base.color;
+
+/**
+ * Expose `TAP`.
+ */
+
+exports = module.exports = TAP;
+
+/**
+ * Initialize a new `TAP` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function TAP(runner) {
+  Base.call(this, runner);
+
+  var self = this
+    , stats = this.stats
+    , total = runner.total
+    , n = 1;
+
+  runner.on('start', function(){
+    console.log('%d..%d', 1, total);
+  });
+
+  runner.on('test end', function(){
+    ++n;
+  });
+
+  runner.on('pending', function(test){
+    console.log('ok %d %s # SKIP -', n, title(test));
+  });
+
+  runner.on('pass', function(test){
+    console.log('ok %d %s', n, title(test));
+  });
+
+  runner.on('fail', function(test, err){
+    console.log('not ok %d %s', n, title(test));
+    console.log(err.stack.replace(/^/gm, '  '));
+  });
+}
+
+/**
+ * Return a TAP-safe title of `test`
+ *
+ * @param {Object} test
+ * @return {String}
+ * @api private
+ */
+
+function title(test) {
+  return test.fullTitle().replace(/#/g, '');
+}
+
+}); // module: reporters/tap.js
+
+require.register("reporters/teamcity.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Teamcity`.
+ */
+
+exports = module.exports = Teamcity;
+
+/**
+ * Initialize a new `Teamcity` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Teamcity(runner) {
+  Base.call(this, runner);
+  var stats = this.stats;
+
+  runner.on('start', function() {
+    console.log("##teamcity[testSuiteStarted name='mocha.suite']");
+  });
+
+  runner.on('test', function(test) {
+    console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
+  });
+
+  runner.on('fail', function(test, err) {
+    console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']");
+  });
+
+  runner.on('pending', function(test) {
+    console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']");
+  });
+
+  runner.on('test end', function(test) {
+    console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']");
+  });
+
+  runner.on('end', function() {
+    console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']");
+  });
+}
+
+/**
+ * Escape the given `str`.
+ */
+
+function escape(str) {
+  return str.replace(/'/g, "|'");
+}
+}); // module: reporters/teamcity.js
+
+require.register("reporters/xunit.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+  , utils = require('../utils')
+  , escape = utils.escape;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Expose `XUnit`.
+ */
+
+exports = module.exports = XUnit;
+
+/**
+ * Initialize a new `XUnit` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function XUnit(runner) {
+  Base.call(this, runner);
+  var stats = this.stats
+    , tests = []
+    , self = this;
+
+  runner.on('test end', function(test){
+    tests.push(test);
+  });
+
+  runner.on('end', function(){
+    console.log(tag('testsuite', {
+        name: 'Mocha Tests'
+      , tests: stats.tests
+      , failures: stats.failures
+      , errors: stats.failures
+      , skip: stats.tests - stats.failures - stats.passes
+      , timestamp: (new Date).toUTCString()
+      , time: stats.duration / 1000
+    }, false));
+
+    tests.forEach(test);
+    console.log('</testsuite>');    
+  });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+XUnit.prototype = new Base;
+XUnit.prototype.constructor = XUnit;
+
+
+/**
+ * Output tag for the given `test.`
+ */
+
+function test(test) {
+  var attrs = {
+      classname: test.parent.fullTitle()
+    , name: test.title
+    , time: test.duration / 1000
+  };
+
+  if ('failed' == test.state) {
+    var err = test.err;
+    attrs.message = escape(err.message);
+    console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
+  } else if (test.pending) {
+    console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
+  } else {
+    console.log(tag('testcase', attrs, true) );
+  }
+}
+
+/**
+ * HTML tag helper.
+ */
+
+function tag(name, attrs, close, content) {
+  var end = close ? '/>' : '>'
+    , pairs = []
+    , tag;
+
+  for (var key in attrs) {
+    pairs.push(key + '="' + escape(attrs[key]) + '"');
+  }
+
+  tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
+  if (content) tag += content + '</' + name + end;
+  return tag;
+}
+
+/**
+ * Return cdata escaped CDATA `str`.
+ */
+
+function cdata(str) {
+  return '<![CDATA[' + escape(str) + ']]>';
+}
+
+}); // module: reporters/xunit.js
+
+require.register("runnable.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+  , debug = require('browser/debug')('runnable');
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+  , setTimeout = global.setTimeout
+  , setInterval = global.setInterval
+  , clearTimeout = global.clearTimeout
+  , clearInterval = global.clearInterval;
+
+/**
+ * Expose `Runnable`.
+ */
+
+module.exports = Runnable;
+
+/**
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Runnable(title, fn) {
+  this.title = title;
+  this.fn = fn;
+  this.async = fn && fn.length;
+  this.sync = ! this.async;
+  this._timeout = 2000;
+  this.timedOut = false;
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Runnable.prototype = new EventEmitter;
+Runnable.prototype.constructor = Runnable;
+
+
+/**
+ * Set & get timeout `ms`.
+ *
+ * @param {Number} ms
+ * @return {Runnable|Number} ms or self
+ * @api private
+ */
+
+Runnable.prototype.timeout = function(ms){
+  if (0 == arguments.length) return this._timeout;
+  debug('timeout %d', ms);
+  this._timeout = ms;
+  if (this.timer) this.resetTimeout();
+  return this;
+};
+
+/**
+ * Return the full title generated by recursively
+ * concatenating the parent's full title.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Runnable.prototype.fullTitle = function(){
+  return this.parent.fullTitle() + ' ' + this.title;
+};
+
+/**
+ * Clear the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.clearTimeout = function(){
+  clearTimeout(this.timer);
+};
+
+/**
+ * Reset the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.resetTimeout = function(){
+  var self = this
+    , ms = this.timeout();
+
+  this.clearTimeout();
+  if (ms) {
+    this.timer = setTimeout(function(){
+      self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
+      self.timedOut = true;
+    }, ms);
+  }
+};
+
+/**
+ * Run the test and invoke `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runnable.prototype.run = function(fn){
+  var self = this
+    , ms = this.timeout()
+    , start = new Date
+    , ctx = this.ctx
+    , finished
+    , emitted;
+
+  if (ctx) ctx.runnable(this);
+
+  // timeout
+  if (this.async) {
+    if (ms) {
+      this.timer = setTimeout(function(){
+        done(new Error('timeout of ' + ms + 'ms exceeded'));
+        self.timedOut = true;
+      }, ms);
+    }
+  }
+
+  // called multiple times
+  function multiple() {
+    if (emitted) return;
+    emitted = true;
+    self.emit('error', new Error('done() called multiple times'));
+  }
+
+  // finished
+  function done(err) {
+    if (self.timedOut) return;
+    if (finished) return multiple();
+    self.clearTimeout();
+    self.duration = new Date - start;
+    finished = true;
+    fn(err);
+  }
+
+  // for .resetTimeout()
+  this.callback = done;
+
+  // async
+  if (this.async) {
+    try {
+      this.fn.call(ctx, function(err){
+        if (err instanceof Error) return done(err);
+        if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
+        done();
+      });
+    } catch (err) {
+      done(err);
+    }
+    return;
+  }
+  
+  // sync
+  try {
+    if (!this.pending) this.fn.call(ctx);
+    this.duration = new Date - start;
+    fn();
+  } catch (err) {
+    fn(err);
+  }
+};
+
+}); // module: runnable.js
+
+require.register("runner.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+  , debug = require('browser/debug')('runner')
+  , Test = require('./test')
+  , utils = require('./utils')
+  , noop = function(){};
+
+/**
+ * Expose `Runner`.
+ */
+
+module.exports = Runner;
+
+/**
+ * Initialize a `Runner` for the given `suite`.
+ *
+ * Events:
+ *
+ *   - `start`  execution started
+ *   - `end`  execution complete
+ *   - `suite`  (suite) test suite execution started
+ *   - `suite end`  (suite) all tests (and sub-suites) have finished
+ *   - `test`  (test) test execution started
+ *   - `test end`  (test) test completed
+ *   - `hook`  (hook) hook execution started
+ *   - `hook end`  (hook) hook complete
+ *   - `pass`  (test) test passed
+ *   - `fail`  (test, err) test failed
+ *
+ * @api public
+ */
+
+function Runner(suite) {
+  var self = this;
+  this._globals = [];
+  this.suite = suite;
+  this.total = suite.total();
+  this.failures = 0;
+  this.on('test end', function(test){ self.checkGlobals(test); });
+  this.on('hook end', function(hook){ self.checkGlobals(hook); });
+  this.grep(/.*/);
+  this.globals(utils.keys(global).concat(['errno']));
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Runner.prototype = new EventEmitter;
+Runner.prototype.constructor = Runner;
+
+
+/**
+ * Run tests with full titles matching `re`. Updates runner.total
+ * with number of tests matched.
+ *
+ * @param {RegExp} re
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.grep = function(re){
+  debug('grep %s', re);
+  this._grep = re;
+  this.total = this.grepTotal(this.suite);
+  return this;
+};
+
+/**
+ * Returns the number of tests matching the grep search for the 
+ * given suite.
+ *
+ * @param {Suite} suite
+ * @return {Number}
+ * @api public
+ */
+
+Runner.prototype.grepTotal = function(suite) {
+  var self = this;
+  var total = 0;
+
+  suite.eachTest(function(test){
+    if (self._grep.test(test.fullTitle())) total++;
+  });
+
+  return total;
+};
+
+/**
+ * Allow the given `arr` of globals.
+ *
+ * @param {Array} arr
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.globals = function(arr){
+  if (0 == arguments.length) return this._globals;
+  debug('globals %j', arr);
+  utils.forEach(arr, function(arr){
+    this._globals.push(arr);
+  }, this);
+  return this;
+};
+
+/**
+ * Check for global variable leaks.
+ *
+ * @api private
+ */
+
+Runner.prototype.checkGlobals = function(test){
+  if (this.ignoreLeaks) return;
+
+  var leaks = utils.filter(utils.keys(global), function(key){
+    return !~utils.indexOf(this._globals, key) && (!global.navigator || 'onerror' !== key);
+  }, this);
+
+  this._globals = this._globals.concat(leaks);
+
+  if (leaks.length > 1) {
+    this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
+  } else if (leaks.length) {
+    this.fail(test, new Error('global leak detected: ' + leaks[0]));
+  }
+};
+
+/**
+ * Fail the given `test`.
+ *
+ * @param {Test} test
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.fail = function(test, err){
+  ++this.failures;
+  test.state = 'failed';
+  if ('string' == typeof err) {
+    err = new Error('the string "' + err + '" was thrown, throw an Error :)');
+  }
+  this.emit('fail', test, err);
+};
+
+/**
+ * Fail the given `hook` with `err`.
+ *
+ * Hook failures (currently) hard-end due
+ * to that fact that a failing hook will
+ * surely cause subsequent tests to fail,
+ * causing jumbled reporting.
+ *
+ * @param {Hook} hook
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.failHook = function(hook, err){
+  this.fail(hook, err);
+  this.emit('end');
+};
+
+/**
+ * Run hook `name` callbacks and then invoke `fn()`.
+ *
+ * @param {String} name
+ * @param {Function} function
+ * @api private
+ */
+
+Runner.prototype.hook = function(name, fn){
+  var suite = this.suite
+    , hooks = suite['_' + name]
+    , ms = suite._timeout
+    , self = this
+    , timer;
+
+  function next(i) {
+    var hook = hooks[i];
+    if (!hook) return fn();
+    self.currentRunnable = hook;
+
+    self.emit('hook', hook);
+
+    hook.on('error', function(err){
+      self.failHook(hook, err);
+    });
+
+    hook.run(function(err){
+      hook.removeAllListeners('error');
+      if (err) return self.failHook(hook, err);
+      self.emit('hook end', hook);
+      next(++i);
+    });
+  }
+
+  process.nextTick(function(){
+    next(0);
+  });
+};
+
+/**
+ * Run hook `name` for the given array of `suites`
+ * in order, and callback `fn(err)`.
+ *
+ * @param {String} name
+ * @param {Array} suites
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hooks = function(name, suites, fn){
+  var self = this
+    , orig = this.suite;
+
+  function next(suite) {
+    self.suite = suite;
+
+    if (!suite) {
+      self.suite = orig;
+      return fn();
+    }
+
+    self.hook(name, function(err){
+      if (err) {
+        self.suite = orig;
+        return fn(err);
+      }
+
+      next(suites.pop());
+    });
+  }
+
+  next(suites.pop());
+};
+
+/**
+ * Run hooks from the top level down.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hookUp = function(name, fn){
+  var suites = [this.suite].concat(this.parents()).reverse();
+  this.hooks(name, suites, fn);
+};
+
+/**
+ * Run hooks from the bottom up.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hookDown = function(name, fn){
+  var suites = [this.suite].concat(this.parents());
+  this.hooks(name, suites, fn);
+};
+
+/**
+ * Return an array of parent Suites from
+ * closest to furthest.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+Runner.prototype.parents = function(){
+  var suite = this.suite
+    , suites = [];
+  while (suite = suite.parent) suites.push(suite);
+  return suites;
+};
+
+/**
+ * Run the current test and callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runTest = function(fn){
+  var test = this.test
+    , self = this;
+
+  try {
+    test.on('error', function(err){
+      self.fail(test, err);
+    });
+    test.run(fn);
+  } catch (err) {
+    fn(err);
+  }
+};
+
+/**
+ * Run tests in the given `suite` and invoke
+ * the callback `fn()` when complete.
+ *
+ * @param {Suite} suite
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runTests = function(suite, fn){
+  var self = this
+    , tests = suite.tests
+    , test;
+
+  function next(err) {
+    // if we bail after first err
+    if (self.failures && suite._bail) return fn();
+
+    // next test
+    test = tests.shift();
+
+    // all done
+    if (!test) return fn();
+
+    // grep
+    if (!self._grep.test(test.fullTitle())) return next();
+
+    // pending
+    if (test.pending) {
+      self.emit('pending', test);
+      self.emit('test end', test);
+      return next();
+    }
+
+    // execute test and hook(s)
+    self.emit('test', self.test = test);
+    self.hookDown('beforeEach', function(){
+      self.currentRunnable = self.test;
+      self.runTest(function(err){
+        test = self.test;
+
+        if (err) {
+          self.fail(test, err);
+          self.emit('test end', test);
+          return self.hookUp('afterEach', next);
+        }
+
+        test.state = 'passed';
+        self.emit('pass', test);
+        self.emit('test end', test);
+        self.hookUp('afterEach', next);
+      });
+    });
+  }
+
+  this.next = next;
+  next();
+};
+
+/**
+ * Run the given `suite` and invoke the
+ * callback `fn()` when complete.
+ *
+ * @param {Suite} suite
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runSuite = function(suite, fn){
+  var total = this.grepTotal(suite)
+    , self = this
+    , i = 0;
+
+  debug('run suite %s', suite.fullTitle());
+
+  if (!total) return fn();
+
+  this.emit('suite', this.suite = suite);
+
+  function next() {
+    var curr = suite.suites[i++];
+    if (!curr) return done();
+    self.runSuite(curr, next);
+  }
+
+  function done() {
+    self.suite = suite;
+    self.hook('afterAll', function(){
+      self.emit('suite end', suite);
+      fn();
+    });
+  }
+
+  this.hook('beforeAll', function(){
+    self.runTests(suite, next);
+  });
+};
+
+/**
+ * Handle uncaught exceptions.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.uncaught = function(err){
+  debug('uncaught exception');
+  var runnable = this.currentRunnable;
+  if ('failed' == runnable.state) return;
+  runnable.clearTimeout();
+  err.uncaught = true;
+  this.fail(runnable, err);
+
+  // recover from test
+  if ('test' == runnable.type) {
+    this.emit('test end', runnable);
+    this.hookUp('afterEach', this.next);
+    return;
+  }
+
+  // bail on hooks
+  this.emit('end');
+};
+
+/**
+ * Run the root suite and invoke `fn(failures)`
+ * on completion.
+ *
+ * @param {Function} fn
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.run = function(fn){
+  var self = this
+    , fn = fn || function(){};
+
+  debug('start');
+
+  // callback
+  this.on('end', function(){
+    debug('end');
+    process.removeListener('uncaughtException', this.uncaught);
+    fn(self.failures);
+  });
+
+  // run suites
+  this.emit('start');
+  this.runSuite(this.suite, function(){
+    debug('finished running');
+    self.emit('end');
+  });
+
+  // uncaught exception
+  process.on('uncaughtException', function(err){
+    self.uncaught(err);
+  });
+
+  return this;
+};
+
+}); // module: runner.js
+
+require.register("suite.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+  , debug = require('browser/debug')('suite')
+  , utils = require('./utils')
+  , Hook = require('./hook');
+
+/**
+ * Expose `Suite`.
+ */
+
+exports = module.exports = Suite;
+
+/**
+ * Create a new `Suite` with the given `title`
+ * and parent `Suite`. When a suite with the
+ * same title is already present, that suite
+ * is returned to provide nicer reporter
+ * and more flexible meta-testing.
+ *
+ * @param {Suite} parent
+ * @param {String} title
+ * @return {Suite}
+ * @api public
+ */
+
+exports.create = function(parent, title){
+  var suite = new Suite(title, parent.ctx);
+  suite.parent = parent;
+  title = suite.fullTitle();
+  parent.addSuite(suite);
+  return suite;
+};
+
+/**
+ * Initialize a new `Suite` with the given
+ * `title` and `ctx`.
+ *
+ * @param {String} title
+ * @param {Context} ctx
+ * @api private
+ */
+
+function Suite(title, ctx) {
+  this.title = title;
+  this.ctx = ctx;
+  this.suites = [];
+  this.tests = [];
+  this._beforeEach = [];
+  this._beforeAll = [];
+  this._afterEach = [];
+  this._afterAll = [];
+  this.root = !title;
+  this._timeout = 2000;
+  this._bail = false;
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Suite.prototype = new EventEmitter;
+Suite.prototype.constructor = Suite;
+
+
+/**
+ * Return a clone of this `Suite`.
+ *
+ * @return {Suite}
+ * @api private
+ */
+
+Suite.prototype.clone = function(){
+  var suite = new Suite(this.title);
+  debug('clone');
+  suite.ctx = this.ctx;
+  suite.timeout(this.timeout());
+  suite.bail(this.bail());
+  return suite;
+};
+
+/**
+ * Set timeout `ms` or short-hand such as "2s".
+ *
+ * @param {Number|String} ms
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.timeout = function(ms){
+  if (0 == arguments.length) return this._timeout;
+  if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000;
+  debug('timeout %d', ms);
+  this._timeout = parseInt(ms, 10);
+  return this;
+};
+
+/**
+ * Sets whether to bail after first error.
+ *
+ * @parma {Boolean} bail
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.bail = function(bail){
+  if (0 == arguments.length) return this._bail;
+  debug('bail %s', bail);
+  this._bail = bail;
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` before running tests.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.beforeAll = function(fn){
+  var hook = new Hook('"before all" hook', fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.ctx = this.ctx;
+  this._beforeAll.push(hook);
+  this.emit('beforeAll', hook);
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` after running tests.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.afterAll = function(fn){
+  var hook = new Hook('"after all" hook', fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.ctx = this.ctx;
+  this._afterAll.push(hook);
+  this.emit('afterAll', hook);
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` before each test case.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.beforeEach = function(fn){
+  var hook = new Hook('"before each" hook', fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.ctx = this.ctx;
+  this._beforeEach.push(hook);
+  this.emit('beforeEach', hook);
+  return this;
+};
+
+/**
+ * Run `fn(test[, done])` after each test case.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.afterEach = function(fn){
+  var hook = new Hook('"after each" hook', fn);
+  hook.parent = this;
+  hook.timeout(this.timeout());
+  hook.ctx = this.ctx;
+  this._afterEach.push(hook);
+  this.emit('afterEach', hook);
+  return this;
+};
+
+/**
+ * Add a test `suite`.
+ *
+ * @param {Suite} suite
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.addSuite = function(suite){
+  suite.parent = this;
+  suite.timeout(this.timeout());
+  suite.bail(this.bail());
+  this.suites.push(suite);
+  this.emit('suite', suite);
+  return this;
+};
+
+/**
+ * Add a `test` to this suite.
+ *
+ * @param {Test} test
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.addTest = function(test){
+  test.parent = this;
+  test.timeout(this.timeout());
+  test.ctx = this.ctx;
+  this.tests.push(test);
+  this.emit('test', test);
+  return this;
+};
+
+/**
+ * Return the full title generated by recursively
+ * concatenating the parent's full title.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Suite.prototype.fullTitle = function(){
+  if (this.parent) {
+    var full = this.parent.fullTitle();
+    if (full) return full + ' ' + this.title;
+  }
+  return this.title;
+};
+
+/**
+ * Return the total number of tests.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+Suite.prototype.total = function(){
+  return utils.reduce(this.suites, function(sum, suite){
+    return sum + suite.total();
+  }, 0) + this.tests.length;
+};
+
+/**
+ * Iterates through each suite recursively to find
+ * all tests. Applies a function in the format
+ * `fn(test)`.
+ *
+ * @param {Function} fn
+ * @return {Suite}
+ * @api private
+ */
+
+Suite.prototype.eachTest = function(fn){
+  utils.forEach(this.tests, fn);
+  utils.forEach(this.suites, function(suite){
+    suite.eachTest(fn);
+  });
+  return this;
+};
+
+}); // module: suite.js
+
+require.register("test.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Runnable = require('./runnable');
+
+/**
+ * Expose `Test`.
+ */
+
+module.exports = Test;
+
+/**
+ * Initialize a new `Test` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Test(title, fn) {
+  Runnable.call(this, title, fn);
+  this.pending = !fn;
+  this.type = 'test';
+}
+
+/**
+ * Inherit from `Runnable.prototype`.
+ */
+
+Test.prototype = new Runnable;
+Test.prototype.constructor = Test;
+
+
+/**
+ * Inspect the context void of private properties.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Test.prototype.inspect = function(){
+  return JSON.stringify(this, function(key, val){
+    return '_' == key[0]
+      ? undefined
+      : 'parent' == key
+        ? '#<Suite>'
+        : val;
+  }, 2);
+};
+}); // module: test.js
+
+require.register("utils.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('browser/fs')
+  , path = require('browser/path')
+  , join = path.join
+  , debug = require('browser/debug')('watch');
+
+/**
+ * Ignored directories.
+ */
+
+var ignore = ['node_modules', '.git'];
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param  {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html) {
+  return String(html)
+    .replace(/&/g, '&amp;')
+    .replace(/"/g, '&quot;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;');
+};
+
+/**
+ * Array#forEach (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.forEach = function(arr, fn, scope) {
+  for (var i = 0, l = arr.length; i < l; i++)
+    fn.call(scope, arr[i], i);
+};
+
+/**
+ * Array#indexOf (<=IE8)
+ *
+ * @parma {Array} arr
+ * @param {Object} obj to find index of
+ * @param {Number} start
+ * @api private
+ */
+
+exports.indexOf = function (arr, obj, start) {
+  for (var i = start || 0, l = arr.length; i < l; i++) {
+    if (arr[i] === obj)
+      return i;
+  }
+  return -1;
+};
+
+/**
+ * Array#reduce (<=IE8)
+ * 
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} initial value
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.reduce = function(arr, fn, val, scope) {
+  var rval = val;
+
+  for (var i = 0, l = arr.length; i < l; i++) {
+    rval = fn.call(scope, rval, arr[i], i, arr);
+  }
+
+  return rval;
+};
+
+/**
+ * Array#filter (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.filter = function(arr, fn, scope) {
+  var ret = [];
+
+  for (var i = 0, l = arr.length; i < l; i++) {
+    var val = arr[i];
+    if (fn.call(scope, val, i, arr))
+      ret.push(val);
+  }
+
+  return ret;
+};
+
+/**
+ * Object.keys (<=IE8)
+ *
+ * @param {Object} obj
+ * @return {Array} keys
+ * @api private
+ */
+
+exports.keys = Object.keys || function(obj) {
+  var keys = []
+    , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
+
+  for (var key in obj) {
+    if (has.call(obj, key)) {
+      keys.push(key);
+    }
+  }
+
+  return keys;
+};
+
+/**
+ * Watch the given `files` for changes
+ * and invoke `fn(file)` on modification.
+ *
+ * @param {Array} files
+ * @param {Function} fn
+ * @api private
+ */
+
+exports.watch = function(files, fn){
+  var options = { interval: 100 };
+  files.forEach(function(file){
+    debug('file %s', file);
+    fs.watchFile(file, options, function(curr, prev){
+      if (prev.mtime < curr.mtime) fn(file);
+    });
+  });
+};
+
+/**
+ * Ignored files.
+ */
+
+function ignored(path){
+  return !~ignore.indexOf(path);
+}
+
+/**
+ * Lookup files in the given `dir`.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+exports.files = function(dir, ret){
+  ret = ret || [];
+
+  fs.readdirSync(dir)
+  .filter(ignored)
+  .forEach(function(path){
+    path = join(dir, path);
+    if (fs.statSync(path).isDirectory()) {
+      exports.files(path, ret);
+    } else if (path.match(/\.(js|coffee)$/)) {
+      ret.push(path);
+    }
+  });
+
+  return ret;
+};
+
+/**
+ * Compute a slug from the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+exports.slug = function(str){
+  return str
+    .toLowerCase()
+    .replace(/ +/g, '-')
+    .replace(/[^-\w]/g, '');
+};
+}); // module: utils.js
+/**
+ * Node shims.
+ *
+ * These are meant only to allow
+ * mocha.js to run untouched, not
+ * to allow running node code in
+ * the browser.
+ */
+
+process = {};
+process.exit = function(status){};
+process.stdout = {};
+global = window;
+
+/**
+ * next tick implementation.
+ */
+
+process.nextTick = (function(){
+  // postMessage behaves badly on IE8
+  if (window.ActiveXObject || !window.postMessage) {
+    return function(fn){ fn() };
+  }
+
+  // based on setZeroTimeout by David Baron
+  // - http://dbaron.org/log/20100309-faster-timeouts
+  var timeouts = []
+    , name = 'mocha-zero-timeout'
+
+  window.addEventListener('message', function(e){
+    if (e.source == window && e.data == name) {
+      if (e.stopPropagation) e.stopPropagation();
+      if (timeouts.length) timeouts.shift()();
+    }
+  }, true);
+
+  return function(fn){
+    timeouts.push(fn);
+    window.postMessage(name, '*');
+  }
+})();
+
+/**
+ * Remove uncaughtException listener.
+ */
+
+process.removeListener = function(e){
+  if ('uncaughtException' == e) {
+    window.onerror = null;
+  }
+};
+
+/**
+ * Implements uncaughtException listener.
+ */
+
+process.on = function(e, fn){
+  if ('uncaughtException' == e) {
+    window.onerror = fn;
+  }
+};
+
+/**
+ * Expose mocha.
+ */
+
+window.mocha = require('mocha');
+
+// boot
+;(function(){
+  var suite = new mocha.Suite('', new mocha.Context)
+    , utils = mocha.utils
+    , options = {}
+
+  /**
+   * Highlight the given string of `js`.
+   */
+
+  function highlight(js) {
+    return js
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;')
+      .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
+      .replace(/('.*?')/gm, '<span class="string">$1</span>')
+      .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
+      .replace(/(\d+)/gm, '<span class="number">$1</span>')
+      .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
+      .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
+  }
+
+  /**
+   * Highlight code contents.
+   */
+
+  function highlightCode() {
+    var code = document.getElementsByTagName('code');
+    for (var i = 0, len = code.length; i < len; ++i) {
+      code[i].innerHTML = highlight(code[i].innerHTML);
+    }
+  }
+
+  /**
+   * Parse the given `qs`.
+   */
+
+  function parse(qs) {
+    return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
+        var i = pair.indexOf('=')
+          , key = pair.slice(0, i)
+          , val = pair.slice(++i);
+
+        obj[key] = decodeURIComponent(val);
+        return obj;
+      }, {});
+  }
+
+  /**
+   * Setup mocha with the given setting options.
+   */
+
+  mocha.setup = function(opts){
+    if ('string' === typeof opts) options.ui = opts;
+    else options = opts;
+
+    ui = mocha.interfaces[options.ui];
+    if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
+    if (options.timeout) suite.timeout(options.timeout);
+    ui(suite);
+    suite.emit('pre-require', window);
+  };
+
+  /**
+   * Run mocha, returning the Runner.
+   */
+
+  mocha.run = function(fn){
+    suite.emit('run');
+    var runner = new mocha.Runner(suite);
+    var Reporter = options.reporter || mocha.reporters.HTML;
+    var reporter = new Reporter(runner);
+    var query = parse(window.location.search || "");
+    if (query.grep) runner.grep(new RegExp(query.grep));
+    if (options.ignoreLeaks) runner.ignoreLeaks = true;
+    if (options.globals) runner.globals(options.globals);
+    runner.globals(['location']);
+    runner.on('end', highlightCode);
+    return runner.run(fn);
+  };
+})();
+})();
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/qs.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/qs.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/browser/qs.js	(revision 533)
@@ -0,0 +1,351 @@
+
+/**
+ * Require the given path.
+ *
+ * @param {String} path
+ * @return {Object} exports
+ * @api public
+ */
+
+function require(p, parent){
+  var path = require.resolve(p)
+    , mod = require.modules[path];
+  if (!mod) throw new Error('failed to require "' + p + '" in ' + parent);
+  if (!mod.exports) {
+    mod.exports = {};
+    mod.client = true;
+    mod.call(mod.exports, mod, mod.exports, require.relative(path));
+  }
+  return mod.exports;
+}
+
+/**
+ * Registered modules.
+ */
+
+require.modules = {};
+
+/**
+ * Resolve `path`.
+ *
+ * @param {String} path
+ * @return {Object} module
+ * @api public
+ */
+
+require.resolve = function(path){
+  var orig = path
+    , reg = path + '.js'
+    , index = path + '/index.js';
+  return require.modules[reg] && reg
+    || require.modules[index] && index
+    || orig;
+};
+
+/**
+ * Register module at `path` with callback `fn`.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ * @api public
+ */
+
+require.register = function(path, fn){
+  require.modules[path] = fn;
+};
+
+/**
+ * Defines and executes anonymous module immediately, while preserving relative
+ * paths.
+ *
+ * @param {String} path
+ * @param {Function} require ref
+ * @api public
+ */
+
+require.exec = function (path, fn) {
+  fn.call(window, require.relative(path));
+};
+
+/**
+ * Return a require function relative to the `parent` path.
+ *
+ * @param {String} parent
+ * @return {Function}
+ * @api private
+ */
+
+require.relative = function(parent) {
+  return function(p){
+    if ('.' != p[0]) return require(p);
+    
+    var path = parent.split('/')
+      , segs = p.split('/');
+    path.pop();
+    
+    for (var i = 0; i < segs.length; i++) {
+      var seg = segs[i];
+      if ('..' == seg) path.pop();
+      else if ('.' != seg) path.push(seg);
+    }
+
+    return require(path.join('/'), parent);
+  };
+};
+// component qs: querystring
+require.register("querystring", function(module, exports, require){
+;(function(){
+
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+  if (parent[key].length == 0) return parent[key] = {};
+  var t = {};
+  for (var i in parent[key]) t[i] = parent[key][i];
+  parent[key] = t;
+  return t;
+}
+
+function parse(parts, parent, key, val) {
+  var part = parts.shift();
+  // end
+  if (!part) {
+    if (Array.isArray(parent[key])) {
+      parent[key].push(val);
+    } else if ('object' == typeof parent[key]) {
+      parent[key] = val;
+    } else if ('undefined' == typeof parent[key]) {
+      parent[key] = val;
+    } else {
+      parent[key] = [parent[key], val];
+    }
+    // array
+  } else {
+    var obj = parent[key] = parent[key] || [];
+    if (']' == part) {
+      if (Array.isArray(obj)) {
+        if ('' != val) obj.push(val);
+      } else if ('object' == typeof obj) {
+        obj[Object.keys(obj).length] = val;
+      } else {
+        obj = parent[key] = [parent[key], val];
+      }
+      // prop
+    } else if (~part.indexOf(']')) {
+      part = part.substr(0, part.length - 1);
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+      // key
+    } else {
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+    }
+  }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+  if (~key.indexOf(']')) {
+    var parts = key.split('[')
+      , len = parts.length
+      , last = len - 1;
+    parse(parts, parent, 'base', val);
+    // optimize
+  } else {
+    if (!isint.test(key) && Array.isArray(parent.base)) {
+      var t = {};
+      for (var k in parent.base) t[k] = parent.base[k];
+      parent.base = t;
+    }
+    set(parent.base, key, val);
+  }
+
+  return parent;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+  var ret = { base: {} };
+  Object.keys(obj).forEach(function(name){
+    merge(ret, name, obj[name]);
+  });
+  return ret.base;
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+  return String(str)
+    .split('&')
+    .reduce(function(ret, pair){
+      try{
+        pair = decodeURIComponent(pair.replace(/\+/g, ' '));
+      } catch(e) {
+        // ignore
+      }
+
+      var eql = pair.indexOf('=')
+        , brace = lastBraceInKey(pair)
+        , key = pair.substr(0, brace || eql)
+        , val = pair.substr(brace || eql, pair.length)
+        , val = val.substr(val.indexOf('=') + 1, val.length);
+
+      // ?foo
+      if ('' == key) key = pair, val = '';
+
+      return merge(ret, key, val);
+    }, { base: {} }).base;
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+  if (null == str || '' == str) return {};
+  return 'object' == typeof str
+    ? parseObject(str)
+    : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+  if (Array.isArray(obj)) {
+    return stringifyArray(obj, prefix);
+  } else if ('[object Object]' == toString.call(obj)) {
+    return stringifyObject(obj, prefix);
+  } else if ('string' == typeof obj) {
+    return stringifyString(obj, prefix);
+  } else {
+    return prefix + '=' + obj;
+  }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+  if (!prefix) throw new TypeError('stringify expects an object');
+  return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+  var ret = [];
+  if (!prefix) throw new TypeError('stringify expects an object');
+  for (var i = 0; i < arr.length; i++) {
+    ret.push(stringify(arr[i], prefix + '['+i+']'));
+  }
+  return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+  var ret = []
+    , keys = Object.keys(obj)
+    , key;
+
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    key = keys[i];
+    ret.push(stringify(obj[key], prefix
+      ? prefix + '[' + encodeURIComponent(key) + ']'
+      : encodeURIComponent(key)));
+  }
+
+  return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+  var v = obj[key];
+  if (undefined === v) {
+    obj[key] = val;
+  } else if (Array.isArray(v)) {
+    v.push(val);
+  } else {
+    obj[key] = [v, val];
+  }
+}
+
+/**
+ * Locate last brace in `str` within the key.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function lastBraceInKey(str) {
+  var len = str.length
+    , brace
+    , c;
+  for (var i = 0; i < len; ++i) {
+    c = str[i];
+    if (']' == c) brace = false;
+    if ('[' == c) brace = true;
+    if ('=' == c && !brace) return i;
+  }
+}
+})();
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/parse.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/parse.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/parse.js	(revision 533)
@@ -0,0 +1,152 @@
+
+if (require.register) {
+  var qs = require('querystring');
+} else {
+  var qs = require('../')
+    , expect = require('expect.js');
+}
+
+describe('qs.parse()', function(){
+  it('should support the basics', function(){
+    expect(qs.parse('0=foo')).to.eql({ '0': 'foo' });
+
+    expect(qs.parse('foo=c++'))
+      .to.eql({ foo: 'c  ' });
+
+    expect(qs.parse('a[>=]=23'))
+      .to.eql({ a: { '>=': '23' }});
+
+    expect(qs.parse('a[<=>]==23'))
+      .to.eql({ a: { '<=>': '=23' }});
+
+    expect(qs.parse('a[==]=23'))
+      .to.eql({ a: { '==': '23' }});
+
+    expect(qs.parse('foo'))
+      .to.eql({ foo: '' });
+
+    expect(qs.parse('foo=bar'))
+      .to.eql({ foo: 'bar' });
+
+    expect(qs.parse(' foo = bar = baz '))
+      .to.eql({ ' foo ': ' bar = baz ' });
+
+    expect(qs.parse('foo=bar=baz'))
+      .to.eql({ foo: 'bar=baz' });
+
+    expect(qs.parse('foo=bar&bar=baz'))
+      .to.eql({ foo: 'bar', bar: 'baz' });
+
+    expect(qs.parse('foo=bar&baz'))
+      .to.eql({ foo: 'bar', baz: '' });
+
+    expect(qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'))
+      .to.eql({
+          cht: 'p3'
+        , chd: 't:60,40'
+        , chs: '250x100'
+        , chl: 'Hello|World'
+      });
+  })
+
+  it('should support encoded = signs', function(){
+    expect(qs.parse('he%3Dllo=th%3Dere'))
+      .to.eql({ 'he=llo': 'th=ere' });
+  })
+
+  it('should support nesting', function(){
+    expect(qs.parse('ops[>=]=25'))
+      .to.eql({ ops: { '>=': '25' }});
+
+    expect(qs.parse('user[name]=tj'))
+      .to.eql({ user: { name: 'tj' }});
+
+    expect(qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'))
+      .to.eql({ user: { name: { first: 'tj', last: 'holowaychuk' }}});
+  })
+
+  it('should support array notation', function(){
+    expect(qs.parse('images[]'))
+      .to.eql({ images: [] });
+
+    expect(qs.parse('user[]=tj'))
+      .to.eql({ user: ['tj'] });
+
+    expect(qs.parse('user[]=tj&user[]=tobi&user[]=jane'))
+      .to.eql({ user: ['tj', 'tobi', 'jane'] });
+
+    expect(qs.parse('user[names][]=tj&user[names][]=tyler'))
+      .to.eql({ user: { names: ['tj', 'tyler'] }});
+
+    expect(qs.parse('user[names][]=tj&user[names][]=tyler&user[email]=tj@vision-media.ca'))
+      .to.eql({ user: { names: ['tj', 'tyler'], email: 'tj@vision-media.ca' }});
+
+    expect(qs.parse('items=a&items=b'))
+      .to.eql({ items: ['a', 'b'] });
+
+    expect(qs.parse('user[names]=tj&user[names]=holowaychuk&user[names]=TJ'))
+      .to.eql({ user: { names: ['tj', 'holowaychuk', 'TJ'] }});
+
+    expect(qs.parse('user[name][first]=tj&user[name][first]=TJ'))
+      .to.eql({ user: { name: { first: ['tj', 'TJ'] }}});
+
+    var o = qs.parse('existing[fcbaebfecc][name][last]=tj')
+    expect(o).to.eql({ existing: { 'fcbaebfecc': { name: { last: 'tj' }}}})
+    expect(Array.isArray(o.existing)).to.equal(false);
+  })
+
+  it('should support arrays with indexes', function(){
+    expect(qs.parse('foo[0]=bar&foo[1]=baz')).to.eql({ foo: ['bar', 'baz'] });
+    expect(qs.parse('foo[1]=bar&foo[0]=baz')).to.eql({ foo: ['baz', 'bar'] });
+    expect(qs.parse('foo[base64]=RAWR')).to.eql({ foo: { base64: 'RAWR' }});
+    expect(qs.parse('foo[64base]=RAWR')).to.eql({ foo: { '64base': 'RAWR' }});
+  })
+
+  it('should expand to an array when dupliate keys are present', function(){
+    expect(qs.parse('items=bar&items=baz&items=raz'))
+      .to.eql({ items: ['bar', 'baz', 'raz'] });
+  })
+
+  it('should support right-hand side brackets', function(){
+    expect(qs.parse('pets=["tobi"]'))
+      .to.eql({ pets: '["tobi"]' });
+
+    expect(qs.parse('operators=[">=", "<="]'))
+      .to.eql({ operators: '[">=", "<="]' });
+
+    expect(qs.parse('op[>=]=[1,2,3]'))
+      .to.eql({ op: { '>=': '[1,2,3]' }});
+
+    expect(qs.parse('op[>=]=[1,2,3]&op[=]=[[[[1]]]]'))
+          .to.eql({ op: { '>=': '[1,2,3]', '=': '[[[[1]]]]' }});
+  })
+
+  it('should support empty values', function(){
+    expect(qs.parse('')).to.eql({});
+    expect(qs.parse(undefined)).to.eql({});
+    expect(qs.parse(null)).to.eql({});
+  })
+
+  it('should transform arrays to objects', function(){
+    expect(qs.parse('foo[0]=bar&foo[bad]=baz')).to.eql({ foo: { 0: "bar", bad: "baz" }});
+    expect(qs.parse('foo[bad]=baz&foo[0]=bar')).to.eql({ foo: { 0: "bar", bad: "baz" }});
+  })
+
+  it('should support malformed uri chars', function(){
+    expect(qs.parse('{%:%}')).to.eql({ '{%:%}': '' });
+    expect(qs.parse('foo=%:%}')).to.eql({ 'foo': '%:%}' });
+  })
+
+  it('should support semi-parsed strings', function(){
+    expect(qs.parse({ 'user[name]': 'tobi' }))
+      .to.eql({ user: { name: 'tobi' }});
+
+    expect(qs.parse({ 'user[name]': 'tobi', 'user[email][main]': 'tobi@lb.com' }))
+      .to.eql({ user: { name: 'tobi', email: { main: 'tobi@lb.com' } }});
+  })
+
+  it('should not produce empty keys', function(){
+    expect(qs.parse('_r=1&'))
+      .to.eql({ _r: '1' })
+  })
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/stringify.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/stringify.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/node_modules/qs/test/stringify.js	(revision 533)
@@ -0,0 +1,81 @@
+
+if (require.register) {
+  var qs = require('querystring');
+} else {
+  var qs = require('../')
+    , expect = require('expect.js');
+}
+
+var date = new Date(0);
+
+var str_identities = {
+  'basics': [
+    { str: 'foo=bar', obj: {'foo' : 'bar'}},
+    { str: 'foo=%22bar%22', obj: {'foo' : '\"bar\"'}},
+    { str: 'foo=', obj: {'foo': ''}},
+    { str: 'foo=1&bar=2', obj: {'foo' : '1', 'bar' : '2'}},
+    { str: 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F', obj: {'my weird field': "q1!2\"'w$5&7/z8)?"}},
+    { str: 'foo%3Dbaz=bar', obj: {'foo=baz': 'bar'}},
+    { str: 'foo=bar&bar=baz', obj: {foo: 'bar', bar: 'baz'}},
+    { str: 'foo=bar&baz=&raz=', obj: { foo: 'bar', baz: null, raz: undefined }},
+    { str: 'foo=bar', obj: { foo: 'bar', '':'' }}
+  ],
+  'escaping': [
+    { str: 'foo=foo%20bar', obj: {foo: 'foo bar'}},
+    { str: 'cht=p3&chd=t%3A60%2C40&chs=250x100&chl=Hello%7CWorld', obj: {
+        cht: 'p3'
+      , chd: 't:60,40'
+      , chs: '250x100'
+      , chl: 'Hello|World'
+    }}
+  ],
+  'nested': [
+    { str: 'foo[0]=bar&foo[1]=quux', obj: {'foo' : ['bar', 'quux']}},
+    { str: 'foo[0]=bar', obj: {foo: ['bar']}},
+    { str: 'foo[0]=1&foo[1]=2', obj: {'foo' : ['1', '2']}},
+    { str: 'foo=bar&baz[0]=1&baz[1]=2&baz[2]=3', obj: {'foo' : 'bar', 'baz' : ['1', '2', '3']}},
+    { str: 'foo[0]=bar&baz[0]=1&baz[1]=2&baz[2]=3', obj: {'foo' : ['bar'], 'baz' : ['1', '2', '3']}},
+    { str: 'x[y][z]=1', obj: {'x' : {'y' : {'z' : '1'}}}},
+    { str: 'x[y][z][0]=1', obj: {'x' : {'y' : {'z' : ['1']}}}},
+    { str: 'x[y][z]=2', obj: {'x' : {'y' : {'z' : '2'}}}},
+    { str: 'x[y][z][0]=1&x[y][z][1]=2', obj: {'x' : {'y' : {'z' : ['1', '2']}}}},
+    { str: 'x[y][0][z]=1', obj: {'x' : {'y' : [{'z' : '1'}]}}},
+    { str: 'x[y][0][z][0]=1', obj: {'x' : {'y' : [{'z' : ['1']}]}}},
+    { str: 'x[y][0][z]=1&x[y][0][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'w' : '2'}]}}},
+    { str: 'x[y][0][v][w]=1', obj: {'x' : {'y' : [{'v' : {'w' : '1'}}]}}},
+    { str: 'x[y][0][z]=1&x[y][0][v][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'v' : {'w' : '2'}}]}}},
+    { str: 'x[y][0][z]=1&x[y][1][z]=2', obj: {'x' : {'y' : [{'z' : '1'}, {'z' : '2'}]}}},
+    { str: 'x[y][0][z]=1&x[y][0][w]=a&x[y][1][z]=2&x[y][1][w]=3', obj: {'x' : {'y' : [{'z' : '1', 'w' : 'a'}, {'z' : '2', 'w' : '3'}]}}},
+    { str: 'user[name][first]=tj&user[name][last]=holowaychuk', obj: { user: { name: { first: 'tj', last: 'holowaychuk' }}}}
+  ],
+  'errors': [
+    { obj: 'foo=bar',     message: 'stringify expects an object' },
+    { obj: ['foo', 'bar'], message: 'stringify expects an object' }
+  ],
+  'numbers': [
+    { str: 'limit[0]=1&limit[1]=2&limit[2]=3', obj: { limit: [1, 2, '3'] }},
+    { str: 'limit=1', obj: { limit: 1 }}
+  ],
+  'others': [
+    { str: 'at=' + encodeURIComponent(date), obj: { at: date } }
+  ]
+};
+
+function test(type) {
+  return function(){
+    var str, obj;
+    for (var i = 0; i < str_identities[type].length; i++) {
+      str = str_identities[type][i].str;
+      obj = str_identities[type][i].obj;
+      expect(qs.stringify(obj)).to.eql(str);
+    }
+  }
+}
+
+describe('qs.stringify()', function(){
+  it('should support the basics', test('basics'))
+  it('should support escapes', test('escaping'))
+  it('should support nesting', test('nested'))
+  it('should support numbers', test('numbers'))
+  it('should support others', test('others'))
+})
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/package.json	(revision 533)
@@ -0,0 +1,55 @@
+{
+  "author": {
+    "name": "mklabs"
+  },
+  "name": "tiny-lr-fork",
+  "description": "Tiny LiveReload server, background-friendly",
+  "version": "0.0.5",
+  "homepage": "https://github.com/mklabs/tiny-lr",
+  "repository": {
+    "url": "git://github.com/mklabs/tiny-lr.git"
+  },
+  "bin": {
+    "tiny-lr-fork": "./bin/tiny-lr"
+  },
+  "main": "./lib",
+  "scripts": {
+    "prepublish:": "npm test",
+    "test": "mocha --reporter list",
+    "test-debug": "DEBUG=tinylr:* mocha --reporter list",
+    "test-debug-all": "DEBUG=* mocha --reporter list"
+  },
+  "dependencies": {
+    "qs": "~0.5.2",
+    "faye-websocket": "~0.4.3",
+    "noptify": "~0.0.3",
+    "debug": "~0.7.0"
+  },
+  "devDependencies": {
+    "mocha": "~1.7.1",
+    "request": "~2.12.0",
+    "supertest": "~0.4.2",
+    "express": "~3.0.6",
+    "connect": "~2.7.2"
+  },
+  "config": {
+    "test_port": "9001"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://github.com/mklabs/tiny-lr/blob/master/LICENSE-MIT"
+    }
+  ],
+  "readme": "This is a fork of tiny-lr. The maintainer of tiny-lr appears to be on a hiatus and this fork takes care of lingering issues until the maintainer of tiny-lr (hopefully) returns.\n\n**Changes made:**\n\n* Quieter, removes `console.log`s\n* Use WSS when livereload.js is on HTTPS\n* Normalize windows paths in livereload.js\n\n---\n\ntiny-lr\n-------\n\nThis script manages a tiny [LiveReload](http://livereload.com/) server\nimplementation you can spawn in the background.\n\nIt exposes:\n\n- a background-friendly bin wrapper (thanks to\n  [@FGRibreau](https://github.com/FGRibreau) [pid.js\n  gist](https://gist.github.com/1846952))\n\n- [Grunt tasks](https://github.com/mklabs/tiny-lr#using-grunt) to start the server and trigger reload notification. Every task\n  name is prefixed by `tinylr-`.\n\n- [Generic targets](https://github.com/mklabs/tiny-lr#using-make) to include in\n  your Makefile (`include node_modules/tiny-lr/tasks/tiny-lr.mk`)\n\nIt doesn't have any watch ability, it must be done at the build process or\napplication level.\n\nInstead, it exposes a very simple API to notify the server that some\nchanges have been made, that is then broadcasted to every livereload client\nconnected.\n\n    # notify a single change\n    curl http://localhost:35729/changed?files=style.css\n\n    # notify using a longer path\n    curl http://localhost:35729/changed?files=js/app.js\n\n    # notify multiple changes, comma or space delimited\n    curl http://localhost:35729/changed?files=index.html,style.css,docs/docco.css\n\nOr you can bulk the information into a POST request, with body as a JSON array of files.\n\n    curl -X POST http://localhost:35729/changed -d '{ \"files\": [\"style.css\", \"app.js\"] }'\n\nAs for the livereload client, you need to install the browser extension:\nhttp://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-\n(**note**: you need to listen on port 35729 to be able to use with your\nbrower extension)\n\nor add the livereload script tag manually:\nhttp://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-\n(and here you can choose whatever port you want)\n\n## Integration\n\nThis package exposes a `bin` you can decide to install globally, but it's not recommended.\n\n    tiny-lr --help\n\n    Usage: tiny-lr [options]\n\n    Options:\n      -h, --help        - Show help usage\n      -v, --version     - Show package version\n      -p, --port        - Port to listen on (default: 35729)\n      --pid             - Path to the generated PID file (default: ./tiny-lr.pid)\n\n\nThe best way to integrate the runner in your workflow is to add it as a `reload`\nstep within your build tool. This build tool can then use the internal binary\nlinked by npm in `node_modules/.bin/tiny-lr` to not rely on global installs (or\nuse the server programmtically).\n\nYou can start the server using the binary provided, or use your own start script.\n\n```js\nvar tinylr = require('tiny-lr');\n\n// standard LiveReload port\nvar port = 35729;\n\n// tinylr(opts) => new tinylr.Server(opts);\ntinylr().listen(port, function() {\n  if(err) {\n    // deal with err\n    return;\n  }\n\n  console.log('... Listening on %s (pid: %s) ...', port);\n})\n```\n\nYou can define your own route and listen for specific request:\n\n```js\nvar server = tinylr();\n\nserver.on('GET /myplace', function(req, res) {\n  res.write('Mine');\n  res.end();\n})\n```\n\nAnd stop the server manually:\n\n```js\nserver.close();\n```\n\nThis will close any websocket connection established and emit a close event.\n\n### Middleware\n\nTo use as a connect / express middleware, tiny-lr needs query /\nbodyParse middlewares prior in the stack.\n\nAny handled requests ends at the tinylr level, not found and errors are\nnexted to the rest of the stack.\n\n```js\n// This binds both express app and tinylr on the same port\nvar app = express();\napp.use(express.query())\n  .use(express.bodyParser())\n  .use(tinylr.middleware({ app: app }))\n  .use(express.static(path.resolve('./')))\n  .use(express.directory(path.resolve('./')))\n  .listen(35729, function() {\n    console.log('Listening on %d', 35729);\n  })\n```\n\nThe port you listen on is important, and tinylr should **always** listen on\nthe LiveReload standard one: `35729`. Otherwise, you won't be able to rely\non the browser extensions, though you can still use the manual snippet\napproach.\n\nYou can also start two different servers, one on your app port, the\nother listening on the LiveReload port. Check the\n`examples/express/server.js` file to see how.\n\n### Using grunt\n\nThis package exposes a `tasks/` directory, that you can use within your Gruntfile with:\n\n```js\ngrunt.loadNpmTasks('tiny-lr');\n```\n\n- tinylr-start    - Starts a new tiny-lr Server, with the provided port.\n- tinylr-reload   - Sends a reload notification to the previously started server.\n\n`tinylr-start` should be used with the `watch` task, probably with an alias\nthat triggers both `tinylr-start watch` tasks.\n\n`tinylr-reload` should be configured as a \"watch\" task in your Gruntfile.\n\n```js\ngrunt.initConfig({\n  watch: {\n    reload: {\n      files: ['**/*.html', '**/*.js', '**/*.css', '**/*.{png,jpg}'],\n      tasks: 'tinylr-reload'\n    }\n  }\n});\n\ngrunt.registerTask('reload', ['tinylr-start', 'watch']);\n```\n\n\n### Using make\n\nSee `tasks/tiny-lr.mk`.\n\nInclude this file into your project Makefile to bring in the following targets:\n\n- start \t\t\t\t\t\t- Start the LiveReload server\n- stop \t\t\t\t\t\t\t- Stops the LiveReload server\n- livereload \t\t\t\t- alias to start\n- livereload-stop \t- aias to stop\n\nThen define your \"empty\" targets, and the list of files you want to monitor.\n\n```make\nCSS_DIR = app/styles\nCSS_FILES = $(shell find $(CSS_DIR) -name '*.css')\n\n# include the livereload targets\ninclude node_modules/tiny-lr/tasks/*.mk\n\n$(CSS_DIR): $(CSS_FILES)\n  @echo CSS files changed: $?\n    @touch $@\n  curl -X POST http://localhost:35729/changed -d '{ \"files\": \"$?\" }'\n\nreload-css: livereload $(CSS_DIR)\n\n.PHONY: reload-css\n```\n\nThe pattern is always the same:\n\n- define a target for your root directory that triggers a POST request\n- `touch` the directory to update its mtime\n- add reload target with `livereload` and the list of files to \"watch\" as\n  prerequisites\n\nYou can chain multiple \"reload\" targets in a single one:\n\n```make\nreload: reload-js reload-css reload-img reload-EVERYTHING\n```\n\nCombine this with [visionmedia/watch](https://github.com/visionmedia/watch) and\nyou have a livereload environment.\n\n    watch make reload\n\n    # add a -q flag to the watch command to suppress most of the annoying output\n    watch -q reload\n\nThe `-q` flag only outputs STDERR, you can in your Makefile redirect the\noutput of your commands to `>&2` to see them in `watch -q` mode.\n\n\n## Tests\n\n    npm test\n\n---\n\n\n# TOC\n   - [tiny-lr](#tiny-lr)\n     - [GET /](#tiny-lr-get-)\n     - [GET /changed](#tiny-lr-get-changed)\n     - [POST /changed](#tiny-lr-post-changed)\n     - [GET /livereload.js](#tiny-lr-get-livereloadjs)\n     - [GET /kill](#tiny-lr-get-kill)\n<a name=\"\" />\n\n<a name=\"tiny-lr\" />\n# tiny-lr\naccepts ws clients.\n\n```js\nvar url = parse(this.request.url);\nvar server = this.app;\n\nvar ws = this.ws = new WebSocket('ws://' + url.host + '/livereload');\n\nws.onopen = function(event) {\n  var hello = {\n    command: 'hello',\n    protocols: ['http://livereload.com/protocols/official-7']\n  };\n\n  ws.send(JSON.stringify(hello));\n};\n\nws.onmessage = function(event) {\n  assert.deepEqual(event.data, JSON.stringify({\n    command: 'hello',\n    protocols: ['http://livereload.com/protocols/official-7'],\n    serverName: 'tiny-lr'\n  }));\n\n  assert.ok(Object.keys(server.clients).length);\n  done();\n};\n```\n\nproperly cleans up established connection on exit.\n\n```js\nvar ws = this.ws;\n\nws.onclose = done.bind(null, null);\n\nrequest(this.server)\n  .get('/kill')\n  .expect(200, function() {\n    console.log('server shutdown');\n  });\n```\n\n<a name=\"tiny-lr\" />\n# tiny-lr\n<a name=\"tiny-lr-get-\" />\n## GET /\nrespond with nothing, but respond.\n\n```js\nrequest(this.server)\n  .get('/')\n  .expect('Content-Type', /json/)\n  .expect('{\"tinylr\":\"Welcome\",\"version\":\"0.0.1\"}')\n  .expect(200, done);\n```\n\nunknown route respond with proper 404 and error message.\n\n```js\nrequest(this.server)\n  .get('/whatev')\n  .expect('Content-Type', /json/)\n  .expect('{\"error\":\"not_found\",\"reason\":\"no such route\"}')\n  .expect(404, done);\n```\n\n<a name=\"tiny-lr-get-changed\" />\n## GET /changed\nwith no clients, no files.\n\n```js\nrequest(this.server)\n  .get('/changed')\n  .expect('Content-Type', /json/)\n  .expect(/\"clients\":\\[\\]/)\n  .expect(/\"files\":\\[\\]/)\n  .expect(200, done);\n```\n\nwith no clients, some files.\n\n```js\nrequest(this.server)\n  .get('/changed?files=gonna.css,test.css,it.css')\n  .expect('Content-Type', /json/)\n  .expect('{\"clients\":[],\"files\":[\"gonna.css\",\"test.css\",\"it.css\"]}')\n  .expect(200, done);\n```\n\n<a name=\"tiny-lr-post-changed\" />\n## POST /changed\nwith no clients, no files.\n\n```js\nrequest(this.server)\n  .post('/changed')\n  .expect('Content-Type', /json/)\n  .expect(/\"clients\":\\[\\]/)\n  .expect(/\"files\":\\[\\]/)\n  .expect(200, done);\n```\n\nwith no clients, some files.\n\n```js\nvar data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] };\n\nrequest(this.server)\n  .post('/changed')\n  .send({ files: data.files })\n  .expect('Content-Type', /json/)\n  .expect(JSON.stringify(data))\n  .expect(200, done);\n```\n\n<a name=\"tiny-lr-get-livereloadjs\" />\n## GET /livereload.js\nrespond with livereload script.\n\n```js\nrequest(this.server)\n  .get('/livereload.js')\n  .expect(/LiveReload/)\n  .expect(200, done);\n```\n\n<a name=\"tiny-lr-get-kill\" />\n## GET /kill\nshutdown the server.\n\n```js\nvar server = this.server;\nrequest(server)\n  .get('/kill')\n  .expect(200, function(err) {\n    if(err) return done(err);\n    assert.ok(!server._handle);\n    done();\n  });\n```\n\n---\n\n- 2013-01-21 - v0.0.5 - [PR #18](https://github.com/mklabs/tiny-lr/pull/18) / [PR #21](https://github.com/mklabs/tiny-lr/pull/21) - https support / expose reload flags through options\n- 2013-01-21 - v0.0.4 - middleware support\n- 2013-01-20 - v0.0.3 - serve livereload from repo (#4)\n- 2013-01-12 - v0.0.2 - tasks - support for grunt 0.3.x (#1)\n- 2013-01-05 - v0.0.1 - Initial release\n",
+  "readmeFilename": "readme.md",
+  "bugs": {
+    "url": "https://github.com/mklabs/tiny-lr/issues"
+  },
+  "_id": "tiny-lr-fork@0.0.5",
+  "dist": {
+    "shasum": "2d1b767461b008c117036f9440e8eb566729f2ae"
+  },
+  "_from": "tiny-lr-fork@0.0.5",
+  "_resolved": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/readme.md
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/readme.md	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/readme.md	(revision 533)
@@ -0,0 +1,397 @@
+This is a fork of tiny-lr. The maintainer of tiny-lr appears to be on a hiatus and this fork takes care of lingering issues until the maintainer of tiny-lr (hopefully) returns.
+
+**Changes made:**
+
+* Quieter, removes `console.log`s
+* Use WSS when livereload.js is on HTTPS
+* Normalize windows paths in livereload.js
+
+---
+
+tiny-lr
+-------
+
+This script manages a tiny [LiveReload](http://livereload.com/) server
+implementation you can spawn in the background.
+
+It exposes:
+
+- a background-friendly bin wrapper (thanks to
+  [@FGRibreau](https://github.com/FGRibreau) [pid.js
+  gist](https://gist.github.com/1846952))
+
+- [Grunt tasks](https://github.com/mklabs/tiny-lr#using-grunt) to start the server and trigger reload notification. Every task
+  name is prefixed by `tinylr-`.
+
+- [Generic targets](https://github.com/mklabs/tiny-lr#using-make) to include in
+  your Makefile (`include node_modules/tiny-lr/tasks/tiny-lr.mk`)
+
+It doesn't have any watch ability, it must be done at the build process or
+application level.
+
+Instead, it exposes a very simple API to notify the server that some
+changes have been made, that is then broadcasted to every livereload client
+connected.
+
+    # notify a single change
+    curl http://localhost:35729/changed?files=style.css
+
+    # notify using a longer path
+    curl http://localhost:35729/changed?files=js/app.js
+
+    # notify multiple changes, comma or space delimited
+    curl http://localhost:35729/changed?files=index.html,style.css,docs/docco.css
+
+Or you can bulk the information into a POST request, with body as a JSON array of files.
+
+    curl -X POST http://localhost:35729/changed -d '{ "files": ["style.css", "app.js"] }'
+
+As for the livereload client, you need to install the browser extension:
+http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-
+(**note**: you need to listen on port 35729 to be able to use with your
+brower extension)
+
+or add the livereload script tag manually:
+http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-
+(and here you can choose whatever port you want)
+
+## Integration
+
+This package exposes a `bin` you can decide to install globally, but it's not recommended.
+
+    tiny-lr --help
+
+    Usage: tiny-lr [options]
+
+    Options:
+      -h, --help        - Show help usage
+      -v, --version     - Show package version
+      -p, --port        - Port to listen on (default: 35729)
+      --pid             - Path to the generated PID file (default: ./tiny-lr.pid)
+
+
+The best way to integrate the runner in your workflow is to add it as a `reload`
+step within your build tool. This build tool can then use the internal binary
+linked by npm in `node_modules/.bin/tiny-lr` to not rely on global installs (or
+use the server programmtically).
+
+You can start the server using the binary provided, or use your own start script.
+
+```js
+var tinylr = require('tiny-lr');
+
+// standard LiveReload port
+var port = 35729;
+
+// tinylr(opts) => new tinylr.Server(opts);
+tinylr().listen(port, function() {
+  if(err) {
+    // deal with err
+    return;
+  }
+
+  console.log('... Listening on %s (pid: %s) ...', port);
+})
+```
+
+You can define your own route and listen for specific request:
+
+```js
+var server = tinylr();
+
+server.on('GET /myplace', function(req, res) {
+  res.write('Mine');
+  res.end();
+})
+```
+
+And stop the server manually:
+
+```js
+server.close();
+```
+
+This will close any websocket connection established and emit a close event.
+
+### Middleware
+
+To use as a connect / express middleware, tiny-lr needs query /
+bodyParse middlewares prior in the stack.
+
+Any handled requests ends at the tinylr level, not found and errors are
+nexted to the rest of the stack.
+
+```js
+// This binds both express app and tinylr on the same port
+var app = express();
+app.use(express.query())
+  .use(express.bodyParser())
+  .use(tinylr.middleware({ app: app }))
+  .use(express.static(path.resolve('./')))
+  .use(express.directory(path.resolve('./')))
+  .listen(35729, function() {
+    console.log('Listening on %d', 35729);
+  })
+```
+
+The port you listen on is important, and tinylr should **always** listen on
+the LiveReload standard one: `35729`. Otherwise, you won't be able to rely
+on the browser extensions, though you can still use the manual snippet
+approach.
+
+You can also start two different servers, one on your app port, the
+other listening on the LiveReload port. Check the
+`examples/express/server.js` file to see how.
+
+### Using grunt
+
+This package exposes a `tasks/` directory, that you can use within your Gruntfile with:
+
+```js
+grunt.loadNpmTasks('tiny-lr');
+```
+
+- tinylr-start    - Starts a new tiny-lr Server, with the provided port.
+- tinylr-reload   - Sends a reload notification to the previously started server.
+
+`tinylr-start` should be used with the `watch` task, probably with an alias
+that triggers both `tinylr-start watch` tasks.
+
+`tinylr-reload` should be configured as a "watch" task in your Gruntfile.
+
+```js
+grunt.initConfig({
+  watch: {
+    reload: {
+      files: ['**/*.html', '**/*.js', '**/*.css', '**/*.{png,jpg}'],
+      tasks: 'tinylr-reload'
+    }
+  }
+});
+
+grunt.registerTask('reload', ['tinylr-start', 'watch']);
+```
+
+
+### Using make
+
+See `tasks/tiny-lr.mk`.
+
+Include this file into your project Makefile to bring in the following targets:
+
+- start 						- Start the LiveReload server
+- stop 							- Stops the LiveReload server
+- livereload 				- alias to start
+- livereload-stop 	- aias to stop
+
+Then define your "empty" targets, and the list of files you want to monitor.
+
+```make
+CSS_DIR = app/styles
+CSS_FILES = $(shell find $(CSS_DIR) -name '*.css')
+
+# include the livereload targets
+include node_modules/tiny-lr/tasks/*.mk
+
+$(CSS_DIR): $(CSS_FILES)
+  @echo CSS files changed: $?
+    @touch $@
+  curl -X POST http://localhost:35729/changed -d '{ "files": "$?" }'
+
+reload-css: livereload $(CSS_DIR)
+
+.PHONY: reload-css
+```
+
+The pattern is always the same:
+
+- define a target for your root directory that triggers a POST request
+- `touch` the directory to update its mtime
+- add reload target with `livereload` and the list of files to "watch" as
+  prerequisites
+
+You can chain multiple "reload" targets in a single one:
+
+```make
+reload: reload-js reload-css reload-img reload-EVERYTHING
+```
+
+Combine this with [visionmedia/watch](https://github.com/visionmedia/watch) and
+you have a livereload environment.
+
+    watch make reload
+
+    # add a -q flag to the watch command to suppress most of the annoying output
+    watch -q reload
+
+The `-q` flag only outputs STDERR, you can in your Makefile redirect the
+output of your commands to `>&2` to see them in `watch -q` mode.
+
+
+## Tests
+
+    npm test
+
+---
+
+
+# TOC
+   - [tiny-lr](#tiny-lr)
+     - [GET /](#tiny-lr-get-)
+     - [GET /changed](#tiny-lr-get-changed)
+     - [POST /changed](#tiny-lr-post-changed)
+     - [GET /livereload.js](#tiny-lr-get-livereloadjs)
+     - [GET /kill](#tiny-lr-get-kill)
+<a name="" />
+
+<a name="tiny-lr" />
+# tiny-lr
+accepts ws clients.
+
+```js
+var url = parse(this.request.url);
+var server = this.app;
+
+var ws = this.ws = new WebSocket('ws://' + url.host + '/livereload');
+
+ws.onopen = function(event) {
+  var hello = {
+    command: 'hello',
+    protocols: ['http://livereload.com/protocols/official-7']
+  };
+
+  ws.send(JSON.stringify(hello));
+};
+
+ws.onmessage = function(event) {
+  assert.deepEqual(event.data, JSON.stringify({
+    command: 'hello',
+    protocols: ['http://livereload.com/protocols/official-7'],
+    serverName: 'tiny-lr'
+  }));
+
+  assert.ok(Object.keys(server.clients).length);
+  done();
+};
+```
+
+properly cleans up established connection on exit.
+
+```js
+var ws = this.ws;
+
+ws.onclose = done.bind(null, null);
+
+request(this.server)
+  .get('/kill')
+  .expect(200, function() {
+    console.log('server shutdown');
+  });
+```
+
+<a name="tiny-lr" />
+# tiny-lr
+<a name="tiny-lr-get-" />
+## GET /
+respond with nothing, but respond.
+
+```js
+request(this.server)
+  .get('/')
+  .expect('Content-Type', /json/)
+  .expect('{"tinylr":"Welcome","version":"0.0.1"}')
+  .expect(200, done);
+```
+
+unknown route respond with proper 404 and error message.
+
+```js
+request(this.server)
+  .get('/whatev')
+  .expect('Content-Type', /json/)
+  .expect('{"error":"not_found","reason":"no such route"}')
+  .expect(404, done);
+```
+
+<a name="tiny-lr-get-changed" />
+## GET /changed
+with no clients, no files.
+
+```js
+request(this.server)
+  .get('/changed')
+  .expect('Content-Type', /json/)
+  .expect(/"clients":\[\]/)
+  .expect(/"files":\[\]/)
+  .expect(200, done);
+```
+
+with no clients, some files.
+
+```js
+request(this.server)
+  .get('/changed?files=gonna.css,test.css,it.css')
+  .expect('Content-Type', /json/)
+  .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}')
+  .expect(200, done);
+```
+
+<a name="tiny-lr-post-changed" />
+## POST /changed
+with no clients, no files.
+
+```js
+request(this.server)
+  .post('/changed')
+  .expect('Content-Type', /json/)
+  .expect(/"clients":\[\]/)
+  .expect(/"files":\[\]/)
+  .expect(200, done);
+```
+
+with no clients, some files.
+
+```js
+var data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] };
+
+request(this.server)
+  .post('/changed')
+  .send({ files: data.files })
+  .expect('Content-Type', /json/)
+  .expect(JSON.stringify(data))
+  .expect(200, done);
+```
+
+<a name="tiny-lr-get-livereloadjs" />
+## GET /livereload.js
+respond with livereload script.
+
+```js
+request(this.server)
+  .get('/livereload.js')
+  .expect(/LiveReload/)
+  .expect(200, done);
+```
+
+<a name="tiny-lr-get-kill" />
+## GET /kill
+shutdown the server.
+
+```js
+var server = this.server;
+request(server)
+  .get('/kill')
+  .expect(200, function(err) {
+    if(err) return done(err);
+    assert.ok(!server._handle);
+    done();
+  });
+```
+
+---
+
+- 2013-01-21 - v0.0.5 - [PR #18](https://github.com/mklabs/tiny-lr/pull/18) / [PR #21](https://github.com/mklabs/tiny-lr/pull/21) - https support / expose reload flags through options
+- 2013-01-21 - v0.0.4 - middleware support
+- 2013-01-20 - v0.0.3 - serve livereload from repo (#4)
+- 2013-01-12 - v0.0.2 - tasks - support for grunt 0.3.x (#1)
+- 2013-01-05 - v0.0.1 - Initial release
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/tasks/tiny-lr.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/tasks/tiny-lr.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/tasks/tiny-lr.js	(revision 533)
@@ -0,0 +1,123 @@
+
+var fs = require('fs');
+var Server = require('..').Server;
+
+// Basic grunt facade to tiny-lr server.
+//
+// XXX: Consider
+//
+// - spawning the server in the background.
+// - changing the reload target to use HTTP requests to notify the server.
+// - providing a `tinylr-stop` task.
+//
+// Examples
+//
+//      grunt tinylr-start &
+//      grunt tinylr-reload:path/to/asset.ext[,...]
+//
+
+module.exports = function(grunt) {
+  var util = grunt.util || grunt.utils;
+  var _ = util._;
+
+  // server instance
+  var server;
+
+  // Task to start up a new tiny-lr Server, with the provided port.
+  //
+  // - options - Hash of options in Gruntfile `tiny-lr` prop with the following
+  //             properties
+  //             :port - The port to listen on (defaults: 35729)
+  //
+  grunt.registerTask('tinylr-start', 'Start the tiny livereload server', function() {
+    var options = _.defaults(grunt.config('tiny-lr') || {}, {
+      port: 35729
+    });
+
+    // if grunt 0.3, build up the list of mtimes to compare
+    changed();
+
+    var done = this.async();
+    server = new Server();
+    grunt.log.writeln('... Starting server on ' + options.port + ' ...');
+    server.listen(options.port, this.async());
+  });
+
+  // Task to send a reload notification to the previously started server.
+  //
+  // This should be configured as a "watch" task in your Gruntfile, and run
+  // after tinylr-start.
+  //
+  // Example
+  //
+  //      watch: {
+  //        reload: {
+  //          files: ['**/*.html', '**/*.js', '**/*.css', '**/*.{png,jpg}'],
+  //          tasks: 'tinylr-reload'
+  //        }
+  //      }
+  //
+  grunt.registerTask('tinylr-reload', 'Sends a reload notification to the livereload server, based on `watchFiles.changed`', function() {
+    if(!server) return;
+    var files = changed();
+    grunt.log.verbose.writeln('... Reloading ' + grunt.log.wordlist(files) + ' ...');
+    server.changed({
+      body: {
+        files: files
+      }
+    });
+  });
+
+  // Helpers
+
+  // This normalize the list of changed files between 0.4 and 0.3. If
+  // `watchFiles` is available, then use that.
+  //
+  // Otherwise, go through each watch config with `reload` as part of their
+  // `tasks`, concat all the files, and maintain a list of mtime. A changed
+  // files is simply a file with a "newer" mtime.
+  function changed() {
+    if(grunt.file.watchFiles) return grunt.file.watchFiles.changed;
+
+    var watch = grunt.config('watch');
+
+    var files = Object.keys(watch).filter(function(target) {
+      var tasks = watch[target].tasks;
+      if(!tasks) return false;
+      return ~tasks.indexOf('reload');
+    }).reduce(function(list, target) {
+      return list.concat(watch[target].files || []);
+    }, []);
+
+    files = grunt.file.expandFiles(files).filter(ignore('node_modules'));
+
+    // stat compare
+    var stats = changed.stats = changed.stats || {};
+
+    var current = files.map(function(filepath) {
+      var stat = fs.statSync(filepath);
+      stat.file = filepath;
+      return stat;
+    }).reduce(function(o, stat) {
+      o[stat.file] = stat.mtime.getTime();
+      return o;
+    }, {});
+
+
+    files = Object.keys(current).filter(function(file) {
+      if(!stats[file]) return true;
+      return stats[file] !== current[file];
+    });
+
+
+    changed.stats = current;
+    return files;
+  }
+
+
+  // filter helper
+  function ignore(pattern) { return function(item) {
+    return !~item.indexOf(pattern);
+  }}
+
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/tasks/tiny-lr.mk
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/tasks/tiny-lr.mk	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/tasks/tiny-lr.mk	(revision 533)
@@ -0,0 +1,49 @@
+# Include this file into your makefile to bring in the following targets:
+#
+# - start 						- Start the LiveReload server
+# - stop 							- Stops the LiveReload server
+# - livereload 				- alias to start
+# - livereload-stop 	- aias to stop
+#
+# Then define your "empty" targets, and the list of files you want to monitor.
+#
+# 		CSS_DIR = app/styles
+# 		CSS_FILES = $(shell find $(CSS_DIR) -name '*.css')
+#
+# 		$(CSS_DIR): $(CSS_FILES)
+#   		@echo CSS files changed: $?
+#				@touch $@
+#   		curl -X POST http://localhost:35729/changed -d '{ "files": "$?" }'
+#
+#   	reload-css: livereload $(CSS_DIR)
+#
+#   	.PHONY: reload-css
+#
+# The pattern is always the same, define a target for your root directory that
+# triggers a POST request and `touch` the directory to update its mtime, a
+# reload target with `livereload` target and the list of files to "watch" as
+# prerequisites
+#
+# You can chain multiple "reload" targets in a single one:
+#
+# 		reload: reload-js reload-css reload-img reload-EVERYTHING
+
+# add tiny-lr to your PATH (only affect the Makefile environment)
+PATH := ./node_modules/.bin:$(PATH)
+
+tiny-lr.pid:
+	@echo ... Starting server, running in background ...
+	@echo ... Run: "make stop" to stop the server ...
+	@tiny-lr &
+
+start: tiny-lr.pid
+
+stop:
+	@[ -a tiny-lr.pid ] && curl http://localhost:35729/kill
+	# Or: @[ -a tiny-lr.pid ] && kill $(shell cat tiny-lr.pid)
+
+livereload: start
+livereload-stop: stop
+
+
+.PHONY: start stop livereload livereload-stop
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/client.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/client.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/client.js	(revision 533)
@@ -0,0 +1,57 @@
+
+var request = require('supertest');
+var assert  = require('assert');
+var parse   = require('url').parse;
+
+var WebSocket = require('faye-websocket').Client;
+var Server = require('..').Server;
+
+describe('tiny-lr', function() {
+
+  before(function(done) {
+    this.app = new Server;
+    this.server = this.app.server;
+    this.request = request(this.server)
+      .get('/')
+      .expect(200, done);
+  });
+
+
+  it('accepts ws clients', function(done) {
+    var url = parse(this.request.url);
+    var server = this.app;
+
+    var ws = this.ws = new WebSocket('ws://' + url.host + '/livereload');
+
+    ws.onopen = function(event) {
+      var hello = {
+        command: 'hello',
+        protocols: ['http://livereload.com/protocols/official-7']
+      };
+
+      ws.send(JSON.stringify(hello));
+    };
+
+    ws.onmessage = function(event) {
+      assert.deepEqual(event.data, JSON.stringify({
+        command: 'hello',
+        protocols: ['http://livereload.com/protocols/official-7'],
+        serverName: 'tiny-lr'
+      }));
+
+      assert.ok(Object.keys(server.clients).length);
+      done();
+    };
+  });
+
+  it('properly cleans up established connection on exit', function(done) {
+    var ws = this.ws;
+
+    ws.onclose = done.bind(null, null);
+
+    request(this.server)
+      .get('/kill')
+      .expect(200, function() {});
+  });
+
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/middleware.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/middleware.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/middleware.js	(revision 533)
@@ -0,0 +1,121 @@
+
+var http    = require('http');
+var assert  = require('assert');
+var connect = require('connect');
+var express = require('express');
+var request = require('supertest');
+var debug   = require('debug')('tinylr:test');
+var Server  = require('..').Server;
+
+var npmenv = process.env;
+
+var port = parseInt(process.env.npm_package_config_test_port || 0, 10);
+
+describe('Connect Middleware', suite('Connect Middleware', connect()));
+describe('Express Middleware', suite('Express Middleware', express()));
+
+// XXX cover up the ws connection done in client.js / server.js tests:w
+function suite(name, app) {return function() {
+
+  before(function() {
+    this.app = app;
+    this.lr = new Server();
+
+    this.app
+      .use(connect.query())
+      .use(connect.bodyParser())
+      .use(this.lr.handler.bind(this.lr));
+
+    this.server = http.createServer(this.app);
+    debug('Start %s suite, listen on %d', name, port);
+    this.server.listen(port);
+  });
+
+
+  after(function(done) {
+    this.server.close(done);
+  });
+
+  describe('GET /', function() {
+    it('respond with nothing, but respond', function(done){
+      request(this.server)
+        .get('/')
+        .expect('Content-Type', /json/)
+        .expect(/\{"tinylr":"Welcome","version":"0.0.[\d]+"\}/)
+        .expect(200, done);
+    });
+
+    it('unknown route are noop with middlewares, next-ing', function(done){
+      request(this.server)
+        .get('/whatev')
+        .expect('Content-Type', 'text/plain')
+        .expect('Cannot GET /whatev')
+        .expect(404, done);
+    });
+  });
+
+
+  describe('GET /changed', function() {
+    it('with no clients, no files', function(done) {
+      request(this.server)
+        .get('/changed')
+        .expect('Content-Type', /json/)
+        .expect(/"clients":\[\]/)
+        .expect(/"files":\[\]/)
+        .expect(200, done);
+    });
+
+    it('with no clients, some files', function(done) {
+      request(this.server)
+        .get('/changed?files=gonna.css,test.css,it.css')
+        .expect('Content-Type', /json/)
+        .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}')
+        .expect(200, done);
+    });
+  });
+
+  describe('POST /changed', function() {
+    it('with no clients, no files', function(done) {
+      request(this.server)
+        .post('/changed')
+        .expect('Content-Type', /json/)
+        .expect(/"clients":\[\]/)
+        .expect(/"files":\[\]/)
+        .expect(200, done);
+    });
+
+    it.skip('with no clients, some files', function(done) {
+      var data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] };
+
+      var r = request(this.server)
+        .post('/changed')
+        .send({ files: data.files })
+        .expect('Content-Type', /json/)
+        .expect(JSON.stringify(data))
+        .expect(200, done);
+    });
+  });
+
+  describe('GET /livereload.js', function() {
+    it('respond with livereload script', function(done) {
+      request(this.server)
+        .get('/livereload.js')
+        .expect(/LiveReload/)
+        .expect(200, done);
+    });
+  });
+
+  describe.skip('GET /kill', function() {
+    it('shutdown the server', function(done) {
+      var server = this.server;
+      request(server)
+        .get('/kill')
+        .expect(200, function(err) {
+          if(err) return done(err);
+          assert.ok(!server._handle);
+          done();
+        });
+    });
+  });
+
+}};
Index: Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/server.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/server.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/node_modules/tiny-lr-fork/test/server.js	(revision 533)
@@ -0,0 +1,96 @@
+
+var request = require('supertest');
+var assert  = require('assert');
+
+var Server = require('..').Server;
+
+describe('tiny-lr', function() {
+
+  beforeEach(function() {
+    this.app = new Server;
+    this.server = this.app.server;
+  });
+
+  describe('GET /', function() {
+    it('respond with nothing, but respond', function(done){
+      request(this.server)
+        .get('/')
+        .expect('Content-Type', /json/)
+        .expect(/\{"tinylr":"Welcome","version":"0.0.[\d]+"\}/)
+        .expect(200, done);
+    });
+
+    it('unknown route respond with proper 404 and error message', function(done){
+      request(this.server)
+        .get('/whatev')
+        .expect('Content-Type', /json/)
+        .expect('{"error":"not_found","reason":"no such route"}')
+        .expect(404, done);
+    });
+  });
+
+
+  describe('GET /changed', function() {
+    it('with no clients, no files', function(done) {
+      request(this.server)
+        .get('/changed')
+        .expect('Content-Type', /json/)
+        .expect(/"clients":\[\]/)
+        .expect(/"files":\[\]/)
+        .expect(200, done);
+    });
+
+    it('with no clients, some files', function(done) {
+      request(this.server)
+        .get('/changed?files=gonna.css,test.css,it.css')
+        .expect('Content-Type', /json/)
+        .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}')
+        .expect(200, done);
+    });
+  });
+
+  describe('POST /changed', function() {
+    it('with no clients, no files', function(done) {
+      request(this.server)
+        .post('/changed')
+        .expect('Content-Type', /json/)
+        .expect(/"clients":\[\]/)
+        .expect(/"files":\[\]/)
+        .expect(200, done);
+    });
+
+    it('with no clients, some files', function(done) {
+      var data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] };
+
+      request(this.server)
+        .post('/changed')
+        .send({ files: data.files })
+        .expect('Content-Type', /json/)
+        .expect(JSON.stringify(data))
+        .expect(200, done);
+    });
+  });
+
+  describe('GET /livereload.js', function() {
+    it('respond with livereload script', function(done) {
+      request(this.server)
+        .get('/livereload.js')
+        .expect(/LiveReload/)
+        .expect(200, done);
+    });
+  });
+
+  describe('GET /kill', function() {
+    it('shutdown the server', function(done) {
+      var server = this.server;
+      request(server)
+        .get('/kill')
+        .expect(200, function(err) {
+          if(err) return done(err);
+          assert.ok(!server._handle);
+          done();
+        });
+    });
+  });
+
+});
Index: Dev/trunk/node_modules/grunt-contrib-watch/package.json
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/package.json	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/package.json	(revision 533)
@@ -0,0 +1,61 @@
+{
+  "name": "grunt-contrib-watch",
+  "description": "Run predefined tasks whenever watched file patterns are added, changed or deleted.",
+  "version": "0.6.1",
+  "homepage": "https://github.com/gruntjs/grunt-contrib-watch",
+  "author": {
+    "name": "Grunt Team",
+    "url": "http://gruntjs.com/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/gruntjs/grunt-contrib-watch.git"
+  },
+  "bugs": {
+    "url": "https://github.com/gruntjs/grunt-contrib-watch/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://github.com/gruntjs/grunt-contrib-watch/blob/master/LICENSE-MIT"
+    }
+  ],
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "grunt nodeunit -v"
+  },
+  "dependencies": {
+    "gaze": "~0.5.1",
+    "tiny-lr-fork": "0.0.5",
+    "lodash": "~2.4.1",
+    "async": "~0.2.9"
+  },
+  "devDependencies": {
+    "grunt": "~0.4.0",
+    "grunt-contrib-jshint": "~0.8.0",
+    "grunt-contrib-nodeunit": "~0.3.3",
+    "grunt-contrib-internal": "~0.4.7",
+    "underscore.string": "~2.3.3"
+  },
+  "peerDependencies": {
+    "grunt": "~0.4.0"
+  },
+  "keywords": [
+    "gruntplugin",
+    "watch"
+  ],
+  "files": [
+    "tasks",
+    "LICENSE-MIT"
+  ],
+  "readme": "# grunt-contrib-watch v0.6.1 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-watch.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-watch)\n\n> Run predefined tasks whenever watched file patterns are added, changed or deleted.\n\n\n\n## Getting Started\nThis plugin requires Grunt `~0.4.0`\n\nIf you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:\n\n```shell\nnpm install grunt-contrib-watch --save-dev\n```\n\nOnce the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:\n\n```js\ngrunt.loadNpmTasks('grunt-contrib-watch');\n```\n\n\n\n\n## Watch task\n_Run this task with the `grunt watch` command._\n\n\n### Settings\n\nThere are a number of options available. Please review the [minimatch options here](https://github.com/isaacs/minimatch#options). As well as some additional options as follows:\n\n#### files\nType: `String|Array`\n\nThis defines what file patterns this task will watch. Can be a string or an array of files and/or minimatch patterns.\n\n#### tasks\nType: `String|Array`\n\nThis defines which tasks to run when a watched file event occurs.\n\n#### options.spawn\nType: `Boolean`\nDefault: true\n\nWhether to spawn task runs in a child process. Setting this option to `false` speeds up the reaction time of the watch (usually 500ms faster for most) and allows subsequent task runs to share the same context. Not spawning task runs can make the watch more prone to failing so please use as needed.\n\nExample:\n```js\nwatch: {\n  scripts: {\n    files: ['**/*.js'],\n    tasks: ['jshint'],\n    options: {\n      spawn: false,\n    },\n  },\n},\n```\n\n*For backwards compatibility the option `nospawn` is still available and will do the opposite of `spawn`.*\n\n#### options.interrupt\nType: `Boolean`\nDefault: false\n\nAs files are modified this watch task will spawn tasks in child processes. The default behavior will only spawn a new child process per target when the previous process has finished. Set the `interrupt` option to true to terminate the previous process and spawn a new one upon later changes.\n\nExample:\n```js\nwatch: {\n  scripts: {\n    files: '**/*.js',\n    tasks: ['jshint'],\n    options: {\n      interrupt: true,\n    },\n  },\n},\n```\n\n#### options.debounceDelay\nType: `Integer`\nDefault: 500\n\nHow long to wait before emitting events in succession for the same filepath and status. For example if your `Gruntfile.js` file was `changed`, a `changed` event will only fire again after the given milliseconds.\n\nExample:\n```js\nwatch: {\n  scripts: {\n    files: '**/*.js',\n    tasks: ['jshint'],\n    options: {\n      debounceDelay: 250,\n    },\n  },\n},\n```\n\n#### options.interval\nType: `Integer`\nDefault: 100\n\nThe `interval` is passed to `fs.watchFile`. Since `interval` is only used by `fs.watchFile` and this watcher also uses `fs.watch`; it is recommended to ignore this option. *Default is 100ms*.\n\n#### options.event\nType: `String|Array`\nDefault: `'all'`\n\nSpecify the type watch event that trigger the specified task. This option can be one or many of: `'all'`, `'changed'`, `'added'` and `'deleted'`.\n\nExample:\n```js\nwatch: {\n  scripts: {\n    files: '**/*.js',\n    tasks: ['generateFileManifest'],\n    options: {\n      event: ['added', 'deleted'],\n    },\n  },\n},\n```\n\n#### options.reload\nType: `Boolean`\nDefault: `false`\n\nBy default, if `Gruntfile.js` is being watched, then changes to it will trigger the watch task to restart, and reload the `Gruntfile.js` changes.\nWhen `reload` is set to `true`, changes to *any* of the watched files will trigger the watch task to restart.\nThis is especially useful if your `Gruntfile.js` is dependent on other files.\n\n```js\nwatch: {\n  configFiles: {\n    files: [ 'Gruntfile.js', 'config/*.js' ],\n    options: {\n      reload: true\n    }\n  }\n}\n```\n\n\n#### options.forever\nType: `Boolean`\nDefault: true\n\nThis is *only a task level option* and cannot be configured per target. By default the watch task will duck punch `grunt.fatal` and `grunt.warn` to try and prevent them from exiting the watch process. If you don't want `grunt.fatal` and `grunt.warn` to be overridden set the `forever` option to `false`.\n\n#### options.dateFormat\nType: `Function`\n\nThis is *only a task level option* and cannot be configured per target. By default when the watch has finished running tasks it will display the message `Completed in 1.301s at Thu Jul 18 2013 14:58:21 GMT-0700 (PDT) - Waiting...`. You can override this message by supplying your own function:\n\n```js\nwatch: {\n  options: {\n    dateFormat: function(time) {\n      grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());\n      grunt.log.writeln('Waiting for more changes...');\n    },\n  },\n  scripts: {\n    files: '**/*.js',\n    tasks: 'jshint',\n  },\n},\n```\n\n#### options.atBegin\nType: `Boolean`\nDefault: false\n\nThis option will trigger the run of each specified task at startup of the watcher.\n\n#### options.livereload\nType: `Boolean|Number|Object`\nDefault: false\n\nSet to `true` or set `livereload: 1337` to a port number to enable live reloading. Default and recommended port is `35729`.\n\nIf enabled a live reload server will be started with the watch task per target. Then after the indicated tasks have ran, the live reload server will be triggered with the modified files.\n\nExample:\n```js\nwatch: {\n  css: {\n    files: '**/*.sass',\n    tasks: ['sass'],\n    options: {\n      livereload: true,\n    },\n  },\n},\n```\n\nIt's possible to get livereload working over https connections. To do this, pass an object to `livereload` with a `key` and `cert` paths specified.\n\nExample:\n```js\nwatch: {\n  css: {\n    files: '**/*.sass',\n    tasks: ['sass'],\n    options: {\n      livereload: {\n        port: 9000,\n        key: grunt.file.read('path/to/ssl.key'),\n        cert: grunt.file.read('path/to/ssl.crt')\n        // you can pass in any other options you'd like to the https server, as listed here: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener\n      }\n    },\n  },\n},\n```\n\n\n#### options.cwd\nType: `String|Object`\nDefault: `process.cwd()`\n\nAbility to set the current working directory. Defaults to `process.cwd()`. Can either be a string to set the cwd to match files and spawn tasks. Or an object to set each independently. Such as `options: { cwd: { files: 'match/files/from/here', spawn: 'but/spawn/files/from/here' } }`.\n\n#### options.livereloadOnError\nType: `Boolean`  \nDefault: `true`  \n\nOption to prevent the livereload if the executed tasks encountered an error.  If set to `false`, the livereload will only be triggered if all tasks completed successfully.\n\n### Examples\n\n```js\n// Simple config to run jshint any time a file is added, changed or deleted\ngrunt.initConfig({\n  watch: {\n    files: ['**/*'],\n    tasks: ['jshint'],\n  },\n});\n```\n\n```js\n// Advanced config. Run specific tasks when specific files are added, changed or deleted.\ngrunt.initConfig({\n  watch: {\n    gruntfile: {\n      files: 'Gruntfile.js',\n      tasks: ['jshint:gruntfile'],\n    },\n    src: {\n      files: ['lib/*.js', 'css/**/*.scss', '!lib/dontwatch.js'],\n      tasks: ['default'],\n    },\n    test: {\n      files: '<%= jshint.test.src %>',\n      tasks: ['jshint:test', 'qunit'],\n    },\n  },\n});\n```\n\n#### Using the `watch` event\nThis task will emit a `watch` event when watched files are modified. This is useful if you would like a simple notification when files are edited or if you're using this task in tandem with another task. Here is a simple example using the `watch` event:\n\n```js\ngrunt.initConfig({\n  watch: {\n    scripts: {\n      files: ['lib/*.js'],\n    },\n  },\n});\ngrunt.event.on('watch', function(action, filepath, target) {\n  grunt.log.writeln(target + ': ' + filepath + ' has ' + action);\n});\n```\n\n**The `watch` event is not intended for replacing the standard Grunt API for configuring and running tasks. If you're trying to run tasks from within the `watch` event you're more than likely doing it wrong. Please read [configuring tasks](http://gruntjs.com/configuring-tasks).**\n\n##### Compiling Files As Needed\nA very common request is to only compile files as needed. Here is an example that will only lint changed files with the `jshint` task:\n\n```js\ngrunt.initConfig({\n  watch: {\n    scripts: {\n      files: ['lib/*.js'],\n      tasks: ['jshint'],\n      options: {\n        spawn: false,\n      },\n    },\n  },\n  jshint: {\n    all: {\n      src: ['lib/*.js'],\n    },\n  },\n});\n\n// on watch events configure jshint:all to only run on changed file\ngrunt.event.on('watch', function(action, filepath) {\n  grunt.config('jshint.all.src', filepath);\n});\n```\n\nIf you need to dynamically modify your config, the `spawn` option must be disabled to keep the watch running under the same context.\n\nIf you save multiple files simultaneously you may opt for a more robust method:\n\n```js\nvar changedFiles = Object.create(null);\nvar onChange = grunt.util._.debounce(function() {\n  grunt.config('jshint.all.src', Object.keys(changedFiles));\n  changedFiles = Object.create(null);\n}, 200);\ngrunt.event.on('watch', function(action, filepath) {\n  changedFiles[filepath] = action;\n  onChange();\n});\n```\n\n#### Live Reloading\nLive reloading is built into the watch task. Set the option `livereload` to `true` to enable on the default port `35729` or set to a custom port: `livereload: 1337`.\n\nThe simplest way to add live reloading to all your watch targets is by setting `livereload` to `true` at the task level. This will run a single live reload server and trigger the live reload for all your watch targets:\n\n```js\ngrunt.initConfig({\n  watch: {\n    options: {\n      livereload: true,\n    },\n    css: {\n      files: ['public/scss/*.scss'],\n      tasks: ['compass'],\n    },\n  },\n});\n```\n\nYou can also configure live reload for individual watch targets or run multiple live reload servers. Just be sure if you're starting multiple servers they operate on different ports:\n\n```js\ngrunt.initConfig({\n  watch: {\n    css: {\n      files: ['public/scss/*.scss'],\n      tasks: ['compass'],\n      options: {\n        // Start a live reload server on the default port 35729\n        livereload: true,\n      },\n    },\n    another: {\n      files: ['lib/*.js'],\n      tasks: ['anothertask'],\n      options: {\n        // Start another live reload server on port 1337\n        livereload: 1337,\n      },\n    },\n    dont: {\n      files: ['other/stuff/*'],\n      tasks: ['dostuff'],\n    },\n  },\n});\n```\n\n##### Enabling Live Reload in Your HTML\nOnce you've started a live reload server you'll be able to access the live reload script. To enable live reload on your page, add a script tag before your closing `</body>` tag pointing to the `livereload.js` script:\n\n```html\n<script src=\"//localhost:35729/livereload.js\"></script>\n```\n\nFeel free to add this script to your template situation and toggle with some sort of `dev` flag.\n\n##### Using Live Reload with the Browser Extension\nInstead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser.\n\nOnce installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the `<script>` tag.\n\n##### Using Connect Middleware\nSince live reloading is used when developing, you may want to disable building for production (and are not using the browser extension). One method is to use Connect middleware to inject the script tag into your page. Try the [connect-livereload](https://github.com/intesso/connect-livereload) middleware for injecting the live reload script into your page.\n\n##### Rolling Your Own Live Reload\nLive reloading is made easy by the library [tiny-lr](https://github.com/mklabs/tiny-lr). It is encouraged to read the documentation for `tiny-lr`. If you would like to trigger the live reload server yourself, simply POST files to the URL: `http://localhost:35729/changed`. Or if you rather roll your own live reload implementation use the following example:\n\n```js\n// Create a live reload server instance\nvar lrserver = require('tiny-lr')();\n\n// Listen on port 35729\nlrserver.listen(35729, function(err) { console.log('LR Server Started'); });\n\n// Then later trigger files or POST to localhost:35729/changed\nlrserver.changed({body:{files:['public/css/changed.css']}});\n```\n\n##### Live Reload with Preprocessors\nAny time a watched file is edited with the `livereload` option enabled, the file will be sent to the live reload server. Some edited files you may desire to have sent to the live reload server, such as when preprocessing (`sass`, `less`, `coffeescript`, etc). As any file not recognized will reload the entire page as opposed to just the `css` or `javascript`.\n\nThe solution is to point a `livereload` watch target to your destination files:\n\n```js\ngrunt.initConfig({\n  sass: {\n    dev: {\n      src: ['src/sass/*.sass'],\n      dest: 'dest/css/index.css',\n    },\n  },\n  watch: {\n    sass: {\n      // We watch and compile sass files as normal but don't live reload here\n      files: ['src/sass/*.sass'],\n      tasks: ['sass'],\n    },\n    livereload: {\n      // Here we watch the files the sass task will compile to\n      // These files are sent to the live reload server after sass compiles to them\n      options: { livereload: true },\n      files: ['dest/**/*'],\n    },\n  },\n});\n```\n\n### FAQs\n\n#### How do I fix the error `EMFILE: Too many opened files.`?\nThis is because of your system's max opened file limit. For OSX the default is very low (256). Temporarily increase your limit with `ulimit -n 10480`, the number being the new max limit.\n\nIn some versions of OSX the above solution doesn't work. In that case try `launchctl limit maxfiles 10480 10480 ` and restart your terminal. See [here](http://superuser.com/questions/261023/how-to-change-default-ulimit-values-in-mac-os-x-10-6).\n\n#### Can I use this with Grunt v0.3?\n`grunt-contrib-watch@0.1.x` is compatible with Grunt v0.3 but it is highly recommended to upgrade Grunt instead.\n\n#### Why is the watch devouring all my memory/cpu?\nLikely because of an enthusiastic pattern trying to watch thousands of files. Such as `'**/*.js'` but forgetting to exclude the `node_modules` folder with `'!**/node_modules/**'`. Try grouping your files within a subfolder or be more explicit with your file matching pattern.\n\nAnother reason if you're watching a large number of files could be the low default `interval`. Try increasing with `options: { interval: 5007 }`. Please see issues [#35](https://github.com/gruntjs/grunt-contrib-watch/issues/145) and [#145](https://github.com/gruntjs/grunt-contrib-watch/issues/145) for more information.\n\n#### Why spawn as child processes as a default?\nThe goal of this watch task is as files are changed, run tasks as if they were triggered by the user themself. Each time a user runs `grunt` a process is spawned and tasks are ran in succession. In an effort to keep the experience consistent and continually produce expected results, this watch task spawns tasks as child processes by default.\n\nSandboxing task runs also allows this watch task to run more stable over long periods of time. As well as more efficiently with more complex tasks and file structures.\n\nSpawning does cause a performance hit (usually 500ms for most environments). It also cripples tasks that rely on the watch task to share the context with each subsequent run (i.e., reload tasks). If you would like a faster watch task or need to share the context please set the `spawn` option to `false`. Just be aware that with this option enabled, the watch task is more prone to failure.\n\n\n## Release History\n\n * 2014-03-19âââv0.6.1âââFix for watch targets named \"default\"\n * 2014-03-11âââv0.6.0âââClear changed files after triggering live reload to ensure they're only triggered once. cwd option now accepts separate settings for files and spawn. Fix to make interrupt work more than once. Enable live reload over HTTPS. Print newline after initial 'Waiting...' Remove deprecated grunt.util libs Add reload option to specify files other than Gruntfile files to reload. Update to gaze@0.5.1 Use fork of tiny-lr (which has quiter operation, support for HTTPS and windows path fixes) Add livereloadOnError, which if set to false will not trigger live reload if there is an error.\n * 2013-08-25âââv0.5.3âââFixed for live reload missing files.\n * 2013-08-16âââv0.5.2âââFixed issue running tasks after gruntfile is reloaded. Ignores empty file paths.\n * 2013-07-20âââv0.5.1âââFixed issue with options resetting.\n * 2013-07-18âââv0.5.0âââAdded target name to watch event. Added atBegin option to run tasks when watcher starts. Changed nospawn option to spawn (nospawn still available for backwards compatibility). Moved libs/vars into top scope to prevent re-init. Bumped Gaze version to ~0.4. Re-grab task/target options upon each task run. Add dateFormat option to override the date/time output upon completion.\n * 2013-05-27âââv0.4.4âââRemove gracefully closing SIGINT. Not needed and causes problems for Windows. Ensure tasks are an array to not conflict with cliArgs.\n * 2013-05-11âââv0.4.3âââOnly group changed files per target to send correct files to live reload.\n * 2013-05-09âââv0.4.2âââFix for closing watchers.\n * 2013-05-09âââv0.4.1âââRemoved \"beep\" notification. Tasks now optional with livereload option. Reverted \"run again\" with interrupt off to fix infinite recursion issue. Watchers now close more properly on task run.\n * 2013-05-03âââv0.4.0âââOption livereload to start live reload servers. Will reload a Gruntfile before running tasks if Gruntfile is modified. Option event to only trigger watch on certain events. Refactor watch task into separate task runs per target. Option forever to override grunt.fatal/warn to help keeping the watch alive with nospawn enabled. Emit a beep upon complete. Logs all watched files with verbose flag set. If interrupt is off, will run the tasks once more if watch triggered during a previous task run. tasks property is optional for use with watch event. Watchers properly closed when exiting.\n * 2013-02-28âââv0.3.1âââFix for top level options.\n * 2013-02-27âââv0.3.0ââânospawn option added to run tasks without spawning as child processes. Watch emits 'watch' events upon files being triggered with grunt.event. Completion time in seconds and date/time shown after tasks ran. Negate file patterns fixed. Tasks debounced individually to handle simultaneous triggering for multiple targets. Errors handled better and viewable with --stack cli option. Code complexity reduced making the watch task code easier to read.\n * 2013-02-15âââv0.2.0âââFirst official release for Grunt 0.4.0.\n * 2013-01-18âââv0.2.0rc7âââUpdating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.\n * 2013-01-09âââv0.2.0rc5âââUpdating to work with grunt v0.4.0rc5.\n * 2012-12-15âââv0.2.0aâââConversion to grunt v0.4 conventions. Remove node v0.6 and grunt v0.3 support. Allow watch task to be renamed. Use grunt.util.spawn \"grunt\" option. Updated to gaze@0.3.0, forceWatchMethod option removed.\n * 2012-11-01âââv0.1.4âââPrevent watch from spawning duplicate watch tasks\n * 2012-10-28âââv0.1.3âââBetter method to spawn the grunt bin Bump gaze to v0.2.0. Better handles some events and new option forceWatchMethod Only support Node.js >= v0.8\n * 2012-10-17âââv0.1.2âââOnly spawn a process per task one at a time Add interrupt option to cancel previous spawned process Grunt v0.3 compatibility changes\n * 2012-10-16âââv0.1.1âââFallback to global grunt bin if local doesnt exist. Fatal if bin cannot be found Update to gaze 0.1.6\n * 2012-10-08âââv0.1.0âââRelease watch task Remove spawn from helper Run on Grunt v0.4\n\n---\n\nTask submitted by [Kyle Robinson Young](http://dontkry.com)\n\n*This file was generated on Wed Mar 19 2014 13:09:11.*\n",
+  "readmeFilename": "README.md",
+  "_id": "grunt-contrib-watch@0.6.1",
+  "dist": {
+    "shasum": "58916bb67ef9bed22355f17cf815b094dc7c58f7"
+  },
+  "_from": "grunt-contrib-watch@",
+  "_resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-0.6.1.tgz"
+}
Index: Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/livereload.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/livereload.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/livereload.js	(revision 533)
@@ -0,0 +1,58 @@
+/*
+ * grunt-contrib-watch
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2014 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+var tinylr = require('tiny-lr-fork');
+var _ = require('lodash');
+
+// Holds the servers out of scope in case watch is reloaded
+var servers = Object.create(null);
+
+module.exports = function(grunt) {
+
+  var defaults = { port: 35729 };
+
+  function LR(options) {
+    if (options === true) {
+      options = defaults;
+    } else if (typeof options === 'number') {
+      options = {port: options};
+    } else {
+      options = _.defaults(options, defaults);
+    }
+    if (servers[options.port]) {
+      this.server = servers[options.port];
+    } else {
+      this.server = tinylr(options);
+      this.server.server.removeAllListeners('error');
+      this.server.server.on('error', function(err) {
+        if (err.code === 'EADDRINUSE') {
+          grunt.fatal('Port ' + options.port + ' is already in use by another process.');
+        } else {
+          grunt.fatal(err);
+        }
+        process.exit(1);
+      });
+      this.server.listen(options.port, function(err) {
+        if (err) { return grunt.fatal(err); }
+        grunt.log.verbose.writeln('Live reload server started on port: ' + options.port);
+      });
+      servers[options.port] = this.server;
+    }
+  }
+
+  LR.prototype.trigger = function(files) {
+    grunt.log.verbose.writeln('Live reloading ' + grunt.log.wordlist(files) + '...');
+    this.server.changed({body:{files:files}});
+  };
+
+  return function(options) {
+    return new LR(options);
+  };
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/taskrun.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/taskrun.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/taskrun.js	(revision 533)
@@ -0,0 +1,112 @@
+/*
+ * grunt-contrib-watch
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2014 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+var path = require('path');
+var EE = require('events').EventEmitter;
+var util = require('util');
+
+module.exports = function(grunt) {
+
+  var livereload = require('./livereload')(grunt);
+
+  // Create a TaskRun on a target
+  function TaskRun(target) {
+    this.name = target.name || 0;
+    this.files = target.files || [];
+    this._getConfig = target._getConfig;
+    this.options = target.options;
+    this.startedAt = false;
+    this.spawned = null;
+    this.changedFiles = Object.create(null);
+    this.spawnTaskFailure = false;
+    this.livereloadOnError = true;
+    if (typeof this.options.livereloadOnError !== 'undefined') {
+      this.livereloadOnError = this.options.livereloadOnError;
+    }
+  }
+
+  var getErrorCount = function(){
+    if (typeof grunt.fail.forever_warncount !== 'undefined') {
+      return grunt.fail.forever_warncount + grunt.fail.forever_errorcount;
+    } else {
+      return grunt.fail.warncount + grunt.fail.errorcount;
+    }
+  };
+
+  // Run it
+  TaskRun.prototype.run = function(done) {
+    var self = this;
+
+    // Dont run if already running
+    if (self.startedAt !== false) { return; }
+
+    // Start this task run
+    self.startedAt = Date.now();
+
+    // reset before each run
+    self.spawnTaskFailure = false;
+    self.errorsAndWarningsCount = getErrorCount();
+
+    // pull the tasks here in case they were changed by a watch event listener
+    self.tasks = self._getConfig('tasks') || [];
+    if (typeof self.tasks === 'string') {
+      self.tasks = [self.tasks];
+    }
+
+    // If no tasks just call done to trigger potential livereload
+    if (self.tasks.length < 1) { return done(); }
+
+    if (self.options.spawn === false || self.options.nospawn === true) {
+      grunt.task.run(self.tasks);
+      done();
+    } else {
+      self.spawned = grunt.util.spawn({
+        // Spawn with the grunt bin
+        grunt: true,
+        // Run from current working dir and inherit stdio from process
+        opts: {
+          cwd: self.options.cwd.spawn,
+          stdio: 'inherit',
+        },
+        // Run grunt this process uses, append the task to be run and any cli options
+        args: self.tasks.concat(self.options.cliArgs || []),
+      }, function(err, res, code) {
+        self.spawnTaskFailure = (code !== 0);
+        if (self.options.interrupt !== true || (code !== 130 && code !== 1)) {
+          // Spawn is done
+          self.spawned = null;
+          done();
+        }
+      });
+    }
+  };
+
+  // When the task run has completed
+  TaskRun.prototype.complete = function() {
+    var time = Date.now() - this.startedAt;
+    this.startedAt = false;
+    if (this.spawned) {
+      this.spawned.kill('SIGINT');
+      this.spawned = null;
+    }
+
+    var taskFailed = this.spawnTaskFailure || (getErrorCount() > this.errorsAndWarningsCount);
+    this.errorsAndWarningsCount = getErrorCount();
+
+    // Trigger livereload if necessary
+    if (this.livereload && (this.livereloadOnError || !taskFailed)) {
+      this.livereload.trigger(Object.keys(this.changedFiles));
+      this.changedFiles = Object.create(null);
+    }
+    return time;
+  };
+
+  return TaskRun;
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/taskrunner.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/taskrunner.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/tasks/lib/taskrunner.js	(revision 533)
@@ -0,0 +1,361 @@
+/*
+ * grunt-contrib-watch
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2014 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+var path = require('path');
+var EE = require('events').EventEmitter;
+var util = require('util');
+var _ = require('lodash');
+var async = require('async');
+
+// Track which targets to run after reload
+var reloadTargets = [];
+
+// A default target name for config where targets are not used (keep this unique)
+var defaultTargetName = '_$_default_$_';
+
+module.exports = function(grunt) {
+
+  var TaskRun = require('./taskrun')(grunt);
+  var livereload = require('./livereload')(grunt);
+
+  function Runner() {
+    EE.call(this);
+    // Name of the task
+    this.name = 'watch';
+    // Options for the runner
+    this.options = {};
+    // Function to close the task
+    this.done = function() {};
+    // Targets available to task run
+    this.targets = Object.create(null);
+    // The queue of task runs
+    this.queue = [];
+    // Whether we're actively running tasks
+    this.running = false;
+    // If a nospawn task has ran (and needs the watch to restart)
+    this.nospawn = false;
+    // Set to true before run() to reload task
+    this.reload = false;
+    // For re-queuing arguments with the task that originally ran this
+    this.nameArgs = [];
+    // A list of changed files to feed to task runs for livereload
+    this.changedFiles = Object.create(null);
+  }
+  util.inherits(Runner, EE);
+
+  // Init a task for taskrun
+  Runner.prototype.init = function init(name, defaults, done) {
+    var self = this;
+
+    self.name = name || grunt.task.current.name || 'watch';
+    self.options = self._options(grunt.config([self.name, 'options']) || {}, defaults || {});
+    self.reload = false;
+    self.nameArgs = (grunt.task.current.nameArgs) ? grunt.task.current.nameArgs : self.name;
+
+    // Normalize cwd option
+    if (typeof self.options.cwd === 'string') {
+      self.options.cwd = { files: self.options.cwd, spawn: self.options.cwd };
+    }
+
+    // Function to call when closing the task
+    self.done = done || grunt.task.current.async();
+
+    // If a default livereload server for all targets
+    // Use task level unless target level overrides
+    var taskLRConfig = grunt.config([self.name, 'options', 'livereload']);
+    if (self.options.target && taskLRConfig) {
+      var targetLRConfig = grunt.config([self.name, self.options.target, 'options', 'livereload']);
+      if (targetLRConfig) {
+        // Dont use task level as target level will be used instead
+        taskLRConfig = false;
+      }
+    }
+    if (taskLRConfig) {
+      self.livereload = livereload(taskLRConfig);
+    }
+
+    // Return the targets normalized
+    var targets = self._getTargets(self.name);
+
+    if (self.running) {
+      // If previously running, complete the last run
+      self.complete();
+    } else if (reloadTargets.length > 0) {
+      // If not previously running but has items in the queue, needs run
+      self.queue = reloadTargets;
+      reloadTargets = [];
+      self.run();
+    } else {
+      // Check whether target's tasks should run at start w/ atBegin option
+      self.queue = targets.filter(function(tr) {
+        return tr.options.atBegin === true && tr.tasks.length > 0;
+      }).map(function(tr) {
+        return tr.name;
+      });
+      if (self.queue.length > 0) {
+        self.run();
+      }
+    }
+
+    return targets;
+  };
+
+  // Normalize targets from config
+  Runner.prototype._getTargets = function _getTargets(name) {
+    var self = this;
+
+    grunt.task.current.requiresConfig(name);
+    var config = grunt.config(name);
+    var onlyTarget = (self.options.target) ? self.options.target : false;
+
+    var targets = (onlyTarget ? [onlyTarget] : Object.keys(config)).filter(function(key) {
+      if (key === 'options') { return false; }
+      return typeof config[key] !== 'string' && !Array.isArray(config[key]);
+    }).map(function(target) {
+      // Fail if any required config properties have been omitted
+      grunt.task.current.requiresConfig([name, target, 'files']);
+      var cfg = grunt.config([name, target]);
+      cfg.name = target;
+      cfg.options = self._options(cfg.options || {}, self.options);
+      self.add(cfg);
+      return cfg;
+    }, self);
+
+    // Allow "basic" non-target format
+    if (typeof config.files === 'string' || Array.isArray(config.files)) {
+      var cfg = {
+        files: config.files,
+        tasks: config.tasks,
+        name: defaultTargetName,
+        options: self._options(config.options || {}, self.options),
+      };
+      targets.push(cfg);
+      self.add(cfg);
+    }
+
+    return targets;
+  };
+
+  // Default options
+  Runner.prototype._options = function _options() {
+    var args = Array.prototype.slice.call(arguments).concat({
+      // The cwd to spawn within
+      cwd: process.cwd(),
+      // Additional cli args to append when spawning
+      cliArgs: _.without.apply(null, [[].slice.call(process.argv, 2)].concat(grunt.cli.tasks)),
+      interrupt: false,
+      nospawn: false,
+      spawn: true,
+      atBegin: false,
+      event: ['all'],
+      target: null,
+    });
+    return _.defaults.apply(_, args);
+  };
+
+  // Run the current queue of task runs
+  Runner.prototype.run = _.debounce(function run() {
+    var self = this;
+    if (self.queue.length < 1) {
+      self.running = false;
+      return;
+    }
+
+    // Re-grab task options in case they changed between runs
+    self.options = self._options(grunt.config([self.name, 'options']) || {}, self.options);
+
+    // If we should interrupt
+    if (self.running === true) {
+      var shouldInterrupt = true;
+      self.queue.forEach(function(name) {
+        var tr = self.targets[name];
+        if (tr && tr.options.interrupt !== true) {
+          shouldInterrupt = false;
+          return false;
+        }
+      });
+      if (shouldInterrupt === true) {
+        self.interrupt();
+      } else {
+        // Dont interrupt the tasks running
+        return;
+      }
+    }
+
+    // If we should reload
+    if (self.reload) { return self.reloadTask(); }
+
+    // Trigger that tasks runs have started
+    self.emit('start');
+    self.running = true;
+
+    // Run each target
+    var shouldComplete = true;
+    async.forEachSeries(self.queue, function(name, next) {
+      var tr = self.targets[name];
+      if (!tr) { return next(); }
+
+      // Re-grab options in case they changed between runs
+      tr.options = self._options(grunt.config([self.name, name, 'options']) || {}, tr.options, self.options);
+
+      if (tr.options.spawn === false || tr.options.nospawn === true) {
+        shouldComplete = false;
+      }
+      tr.run(next);
+    }, function() {
+      if (shouldComplete) {
+        self.complete();
+      } else {
+        grunt.task.mark().run(self.nameArgs);
+        self.done();
+      }
+    });
+  }, 250);
+
+  // Push targets onto the queue
+  Runner.prototype.add = function add(target) {
+    var self = this;
+    if (!this.targets[target.name || 0]) {
+
+      // Private method for getting latest config for a watch target
+      target._getConfig = function(name) {
+        var cfgPath = [self.name];
+        if (target.name !== defaultTargetName) { cfgPath.push(target.name); }
+        if (name) { cfgPath.push(name); }
+        return grunt.config(cfgPath);
+      };
+
+      // Create a new TaskRun instance
+      var tr = new TaskRun(target);
+
+      // Add livereload to task runs
+      // Get directly from config as task level options are merged.
+      // We only want a single default LR server and then
+      // allow each target to override their own.
+      var lrconfig = grunt.config([this.name, target.name || 0, 'options', 'livereload']);
+      if (lrconfig) {
+        tr.livereload = livereload(lrconfig);
+      } else if (this.livereload && lrconfig !== false) {
+        tr.livereload = this.livereload;
+      }
+
+      return this.targets[tr.name] = tr;
+    }
+    return false;
+  };
+
+  // Do this when queued task runs have completed/scheduled
+  Runner.prototype.complete = function complete() {
+    var self = this;
+    if (self.running === false) { return; }
+    self.running = false;
+    var time = 0;
+    for (var i = 0, len = self.queue.length; i < len; ++i) {
+      var name = self.queue[i];
+      var target = self.targets[name];
+      if (!target) { return; }
+      if (target.startedAt !== false) {
+        time += target.complete();
+        self.queue.splice(i--, 1);
+        len--;
+
+        // if we're just livereloading and no tasks
+        // it can happen too fast and we dont report it
+        if (target.options.livereload && target.tasks.length < 1) {
+          time += 0.0001;
+        }
+      }
+    }
+    var elapsed = (time > 0) ? Number(time / 1000) : 0;
+    self.changedFiles = Object.create(null);
+    self.emit('end', elapsed);
+  };
+
+  // Run through completing every target in the queue
+  Runner.prototype._completeQueue = function _completeQueue() {
+    var self = this;
+    self.queue.forEach(function(name) {
+      var target = self.targets[name];
+      if (!target) { return; }
+      target.complete();
+    });
+  };
+
+  // Interrupt the running tasks
+  Runner.prototype.interrupt = function interrupt() {
+    var self = this;
+    self._completeQueue();
+    grunt.task.clearQueue();
+    self.emit('interrupt');
+  };
+
+  // Attempt to make this task run forever
+  Runner.prototype.forever = function forever() {
+    var self = this;
+    function rerun() {
+      // Clear queue and rerun to prevent failing
+      self._completeQueue();
+      grunt.task.clearQueue();
+      grunt.task.run(self.nameArgs);
+      self.running = false;
+    }
+    grunt.fail.forever_warncount = 0;
+    grunt.fail.forever_errorcount = 0;
+    grunt.warn = grunt.fail.warn = function(e) {
+      grunt.fail.forever_warncount ++;
+      var message = typeof e === 'string' ? e : e.message;
+      grunt.log.writeln(('Warning: ' + message).yellow);
+      if (!grunt.option('force')) {
+        rerun();
+      }
+    };
+    grunt.fatal = grunt.fail.fatal = function(e) {
+      grunt.fail.forever_errorcount ++;
+      var message = typeof e === 'string' ? e : e.message;
+      grunt.log.writeln(('Fatal error: ' + message).red);
+      rerun();
+    };
+  };
+
+  // Clear the require cache for all passed filepaths.
+  Runner.prototype.clearRequireCache = function() {
+    // If a non-string argument is passed, it's an array of filepaths, otherwise
+    // each filepath is passed individually.
+    var filepaths = typeof arguments[0] !== 'string' ? arguments[0] : Array.prototype.slice(arguments);
+    // For each filepath, clear the require cache, if necessary.
+    filepaths.forEach(function(filepath) {
+      var abspath = path.resolve(filepath);
+      if (require.cache[abspath]) {
+        grunt.verbose.write('Clearing require cache for "' + filepath + '" file...').ok();
+        delete require.cache[abspath];
+      }
+    });
+  };
+
+  // Reload this watch task, like when a Gruntfile is edited
+  Runner.prototype.reloadTask = function() {
+    var self = this;
+    // Which targets to run after reload
+    reloadTargets = self.queue;
+    self.emit('reload', reloadTargets);
+
+    // Re-init the watch task config
+    grunt.task.init([self.name]);
+
+    // Complete all running tasks
+    self._completeQueue();
+
+    // Run the watch task again
+    grunt.task.run(self.nameArgs);
+    self.done();
+  };
+
+  return new Runner();
+};
Index: Dev/trunk/node_modules/grunt-contrib-watch/tasks/watch.js
===================================================================
--- Dev/trunk/node_modules/grunt-contrib-watch/tasks/watch.js	(revision 533)
+++ Dev/trunk/node_modules/grunt-contrib-watch/tasks/watch.js	(revision 533)
@@ -0,0 +1,177 @@
+/*
+ * grunt-contrib-watch
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2014 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+var path = require('path');
+var Gaze = require('gaze').Gaze;
+var _ = require('lodash');
+var waiting = 'Waiting...';
+var changedFiles = Object.create(null);
+var watchers = [];
+
+module.exports = function(grunt) {
+  'use strict';
+
+  var taskrun = require('./lib/taskrunner')(grunt);
+
+  // Default date format logged
+  var dateFormat = function(time) {
+    grunt.log.writeln(String(
+      'Completed in ' +
+      time.toFixed(3) +
+      's at ' +
+      (new Date()).toString()
+    ).cyan + ' - ' + waiting);
+  };
+
+  // When task runner has started
+  taskrun.on('start', function() {
+    Object.keys(changedFiles).forEach(function(filepath) {
+      // Log which file has changed, and how.
+      grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.');
+    });
+    // Reset changedFiles
+    changedFiles = Object.create(null);
+  });
+
+  // When task runner has ended
+  taskrun.on('end', function(time) {
+    if (time > 0) {
+      dateFormat(time);
+    }
+  });
+
+  // When a task run has been interrupted
+  taskrun.on('interrupt', function() {
+    grunt.log.writeln('').write('Scheduled tasks have been interrupted...'.yellow);
+  });
+
+  // When taskrun is reloaded
+  taskrun.on('reload', function() {
+    taskrun.clearRequireCache(Object.keys(changedFiles));
+    grunt.log.writeln('').writeln('Reloading watch config...'.cyan);
+  });
+
+  grunt.registerTask('watch', 'Run predefined tasks whenever watched files change.', function(target) {
+    var self = this;
+    var name = self.name || 'watch';
+
+    // Close any previously opened watchers
+    watchers.forEach(function(watcher) {
+      watcher.close();
+    });
+    watchers = [];
+
+    // Never gonna give you up, never gonna let you down
+    if (grunt.config([name, 'options', 'forever']) !== false) {
+      taskrun.forever();
+    }
+
+    // If a custom dateFormat function
+    var df = grunt.config([name, 'options', 'dateFormat']);
+    if (typeof df === 'function') {
+      dateFormat = df;
+    }
+
+    if (taskrun.running === false) { grunt.log.writeln(waiting); }
+
+    // initialize taskrun
+    var targets = taskrun.init(name, {target: target});
+
+    targets.forEach(function(target, i) {
+      if (typeof target.files === 'string') { target.files = [target.files]; }
+
+      // Process into raw patterns
+      var patterns = _.chain(target.files).flatten().map(function(pattern) {
+        return grunt.config.process(pattern);
+      }).value();
+
+      // Validate the event option
+      if (typeof target.options.event === 'string') {
+        target.options.event = [target.options.event];
+      }
+
+      // Set cwd if options.cwd.file is set
+      if (typeof target.options.cwd !== 'string' && target.options.cwd.files) {
+        target.options.cwd = target.options.cwd.files;
+      }
+
+      // Create watcher per target
+      watchers.push(new Gaze(patterns, target.options, function(err) {
+        if (err) {
+          if (typeof err === 'string') { err = new Error(err); }
+          grunt.log.writeln('ERROR'.red);
+          grunt.fatal(err);
+          return taskrun.done();
+        }
+
+        // Log all watched files with --verbose set
+        if (grunt.option('verbose')) {
+          var watched = this.watched();
+          Object.keys(watched).forEach(function(watchedDir) {
+            watched[watchedDir].forEach(function(watchedFile) {
+              grunt.log.writeln('Watching ' + path.relative(process.cwd(), watchedFile) + ' for changes.');
+            });
+          });
+        }
+
+        // On changed/added/deleted
+        this.on('all', function(status, filepath) {
+
+          // Skip events not specified
+          if (!_.contains(target.options.event, 'all') &&
+              !_.contains(target.options.event, status)) {
+            return;
+          }
+
+          filepath = path.relative(process.cwd(), filepath);
+
+          // Skip empty filepaths
+          if (filepath === '') {
+            return;
+          }
+
+          // If Gruntfile.js changed, reload self task
+          if (target.options.reload || /gruntfile\.(js|coffee)/i.test(filepath)) {
+            taskrun.reload = true;
+          }
+
+          // Emit watch events if anyone is listening
+          if (grunt.event.listeners('watch').length > 0) {
+            grunt.event.emit('watch', status, filepath, target.name);
+          }
+
+          // Group changed files only for display
+          changedFiles[filepath] = status;
+
+          // Add changed files to the target
+          if (taskrun.targets[target.name]) {
+            if (!taskrun.targets[target.name].changedFiles) {
+              taskrun.targets[target.name].changedFiles = Object.create(null);
+            }
+            taskrun.targets[target.name].changedFiles[filepath] = status;
+          }
+
+          // Queue the target
+          if (taskrun.queue.indexOf(target.name) === -1) {
+            taskrun.queue.push(target.name);
+          }
+
+          // Run the tasks
+          taskrun.run();
+        });
+
+        // On watcher error
+        this.on('error', function(err) {
+          if (typeof err === 'string') { err = new Error(err); }
+          grunt.log.error(err.message);
+        });
+      }));
+    });
+
+  });
+};
