diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/package.json b/node_modules/grunt-coffee/node_modules/coffee-script/package.json index d4f1307..45da57c 100644 --- a/node_modules/grunt-coffee/node_modules/coffee-script/package.json +++ b/node_modules/grunt-coffee/node_modules/coffee-script/package.json @@ -39,6 +39,7 @@ "jison": ">=0.2.0" }, "readme": "\n {\n } } {\n { { } }\n } }{ {\n { }{ } } _____ __ __\n ( }{ }{ { ) / ____| / _|/ _|\n .- { { } { }} -. | | ___ | |_| |_ ___ ___\n ( ( } { } { } } ) | | / _ \\| _| _/ _ \\/ _ \\\n |`-..________ ..-'| | |___| (_) | | | || __/ __/\n | | \\_____\\___/|_| |_| \\___|\\___|\n | ;--.\n | (__ \\ _____ _ _\n | | ) ) / ____| (_) | |\n | |/ / | (___ ___ _ __ _ _ __ | |_\n | ( / \\___ \\ / __| '__| | '_ \\| __|\n | |/ ____) | (__| | | | |_) | |_\n | | |_____/ \\___|_| |_| .__/ \\__|\n `-.._________..-' | |\n |_|\n\n\n CoffeeScript is a little language that compiles into JavaScript.\n\n Install Node.js, and then the CoffeeScript compiler:\n sudo bin/cake install\n\n Or, if you have the Node Package Manager installed:\n npm install -g coffee-script\n (Leave off the -g if you don't wish to install globally.)\n\n Execute a script:\n coffee /path/to/script.coffee\n\n Compile a script:\n coffee -c /path/to/script.coffee\n\n For documentation, usage, and examples, see:\n http://coffeescript.org/\n\n To suggest a feature, report a bug, or general discussion:\n http://github.com/jashkenas/coffee-script/issues/\n\n If you'd like to chat, drop by #coffeescript on Freenode IRC,\n or on webchat.freenode.net.\n\n The source repository:\n git://github.com/jashkenas/coffee-script.git\n\n All contributors are listed here:\n http://github.com/jashkenas/coffee-script/contributors\n", + "readmeFilename": "README", "_id": "coffee-script@1.3.3", "_from": "coffee-script@~1.3.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/.npmignore index fabc13c..25f5634 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/.npmignore +++ b/node_modules/grunt-coffee/node_modules/grunt/.npmignore @@ -1,2 +1,2 @@ -/node_modules/ -/foo/ +node_modules +/tmp diff --git a/node_modules/grunt-coffee/node_modules/grunt/README.md b/node_modules/grunt-coffee/node_modules/grunt/README.md index 543bc6b..9012df8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/README.md @@ -4,24 +4,24 @@ Grunt is a task-based command line build tool for JavaScript projects. _Grunt is currently in beta. While I'm already using it on multiple projects, it might have a minor issue or two. And things might change before its final release, based on your feedback. Please try it out in a project, and [make suggestions][issues] or [report bugs][issues]!_ ## Getting started -Be sure to read the [getting started guide](/cowboy/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project. In addition, check out the [example gruntfiles](/cowboy/grunt/blob/master/docs/example_gruntfiles.md) which highlight a number of fairly common configurations. +Be sure to read the [getting started guide](/gruntjs/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project. In addition, check out the [example gruntfiles](/gruntjs/grunt/blob/master/docs/example_gruntfiles.md) which highlight a number of fairly common configurations. ## Built-in tasks As of now, grunt has the following predefined tasks that you can use in your project: -* [concat](/cowboy/grunt/blob/master/docs/task_concat.md) - Concatenate files. -* [init](/cowboy/grunt/blob/master/docs/task_init.md) - Generate project scaffolding from a predefined template. -* [lint](/cowboy/grunt/blob/master/docs/task_lint.md) - Validate files with [JSHint][jshint]. -* [min](/cowboy/grunt/blob/master/docs/task_min.md) - Minify files with [UglifyJS][uglify]. -* [qunit](/cowboy/grunt/blob/master/docs/task_qunit.md) - Run [QUnit][qunit] unit tests in a headless [PhantomJS][phantom] instance. -* [server](/cowboy/grunt/blob/master/docs/task_server.md) - Start a static web server. +* [concat](/gruntjs/grunt/blob/master/docs/task_concat.md) - Concatenate files. +* [init](/gruntjs/grunt/blob/master/docs/task_init.md) - Generate project scaffolding from a predefined template. +* [lint](/gruntjs/grunt/blob/master/docs/task_lint.md) - Validate files with [JSHint][jshint]. +* [min](/gruntjs/grunt/blob/master/docs/task_min.md) - Minify files with [UglifyJS][uglify]. +* [qunit](/gruntjs/grunt/blob/master/docs/task_qunit.md) - Run [QUnit][qunit] unit tests in a headless [PhantomJS][phantom] instance. +* [server](/gruntjs/grunt/blob/master/docs/task_server.md) - Start a static web server. * test - Run unit tests with [nodeunit][nodeunit]. * watch - Run predefined tasks whenever watched files change. _(More documentation forthcoming)_ ## Custom tasks -In addition to the built-in tasks, you can create your own tasks. Don't like a built-in task's default behavior? Override it. Check out the [grunt API documentation](/cowboy/grunt/blob/master/docs/api.md) and the [built-in tasks source](/cowboy/grunt/blob/master/tasks) for everything you need to know about creating custom tasks. +In addition to the built-in tasks, you can create your own tasks. Don't like a built-in task's default behavior? Override it. Check out the [grunt API documentation](/gruntjs/grunt/blob/master/docs/api.md) and the [built-in tasks source](/gruntjs/grunt/blob/master/tasks) for everything you need to know about creating custom tasks. ## Documentation Take a look at the [documentation table of contents][docs] for all the things. @@ -35,13 +35,15 @@ Being primarily a JavaScript developer, I decided to use [Node.js][node] and [np Grunt is available as an [npm][npm] module. If you install grunt globally via `npm install -g grunt`, it will be available for use in all of your projects. Once grunt has been installed, you can type `grunt --help` at the command line for more information. And if you want to see grunt "grunt" itself, cd into grunt's directory and type `grunt` -_Note: in Windows, you may need to run grunt as `grunt.cmd`. See the [FAQ](/cowboy/grunt/blob/master/docs/faq.md) for more Windows-specific information._ +_Note: in Windows, you may need to run grunt as `grunt.cmd`. See the [FAQ](/gruntjs/grunt/blob/master/docs/faq.md) for more Windows-specific information._ -For projects already using grunt, you're done. Otherwise, if you're adding grunt to an existing project or starting from scratch, check out the [getting started guide](/cowboy/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project. +For projects already using grunt, you're done. Otherwise, if you're adding grunt to an existing project or starting from scratch, check out the [getting started guide](/gruntjs/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project. ## Release History _(Until v1.0.0, this will only be updated when major or breaking changes are made)_ +* 2012/10/15 - v0.3.17 - Updating JSHint to 0.9.1. Better stack traces. And a few QUnit task fixes. +* 2012/10/01 - v0.3.16 - Updated URLs to reflect new website and source location. Tweaks to the "jquery" and "commonjs" init templates. Fixed an issue when exiting due to warning or fatal error. * 2012/09/04 - v0.3.15 - Fixing a minor problem with renaming multi tasks. * 2012/08/29 - v0.3.14 - Grunt plugins lacking package.json keywords should work again. * 2012/08/27 - v0.3.13 - Fixed Node.js 0.8.x path.existsSync warning. Updated connect, nodeunit, uglify-js deps to latest. Updated docs. Grunt plugins generated with init:gruntplugin no longer include grunt as a dependency. Added preliminary support for "collection" plugins. @@ -65,12 +67,12 @@ _(Until v1.0.0, this will only be updated when major or breaking changes are mad ## License Copyright (c) 2012 "Cowboy" Ben Alman Licensed under the MIT license. - + -[docs]: /cowboy/grunt/blob/master/docs/toc.md -[docs-init]: /cowboy/grunt/blob/master/docs/task_init.md -[issues]: /cowboy/grunt/issues +[docs]: /gruntjs/grunt/blob/master/docs/toc.md +[docs-init]: /gruntjs/grunt/blob/master/docs/task_init.md +[issues]: /gruntjs/grunt/issues [node]: http://nodejs.org/ [npm]: http://npmjs.org/ diff --git a/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp b/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp index b1c8f1f..072b2dd 100755 --- a/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp +++ b/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp @@ -12,7 +12,7 @@ if {$argc == 0} { foreach template $templates { -set project "grunt-$template-example" +set project "grunt-init-$template-sample" # Disable git pushing when debugging. set gitpush 1 @@ -50,7 +50,7 @@ send "mkdir $project && cd $project\r" expect "$ " send "git init\r" expect "$ " -send "git remote add origin git@github.com:cowboy/$project.git\r" +send "git remote add origin git@github.com:gruntjs/$project.git\r" # Note that the "--no-color" will be stripped out later. expect "$ " @@ -62,9 +62,8 @@ expect "Please answer the following:" # Loop over all prompts. expect { "Do you need to make any changes to the above before continuing? (y/N)" {send "\r"} - "Project name (jquery.grunt-jquery-example)" {send "jquery.grunt-example\r"; exp_continue} - "Project title (jQuery Grunt Example)" {send "Grunt jQuery Example Plugin\r"; exp_continue} - "Description" {send "This is example output generated by the \"grunt init:$template\" task."; exp_continue} + "Project name (grunt-init-jquery-sample)" {send "grunt-sample\r"; exp_continue} + "Project title (Grunt Sample)" {send "Sample Grunt jQuery Plugin\r"; exp_continue} ") " {send "\r"; exp_continue} } @@ -84,7 +83,7 @@ send "tree\r" expect "$ " send "git add .\r" expect "$ " -send "git commit -m 'Committing example \"grunt init:$template\" task output.'\r" +send "git commit -m 'Committing sample \"grunt init:$template\" task output.'\r" # Session logging stops here. expect "$ " @@ -92,12 +91,12 @@ send "# EOF\n" # Add meta-content to the README. expect "$ " -send "echo -e '# Grunt \"init:$template\" example +send "echo -e '# Grunt \"init:$template\" sample -This is example output generated by the \"grunt init:$template\" task. +This is sample output generated by the \"grunt init:$template\" task. _Note: this repository was generated dynamically using $version. Instead of -reporting issues here, please report any issues with this repository as +reporting issues here, please report any issues with this init template as \[grunt issues\]\[issues\]. Instead of watching or forking this repository, watch \[grunt\]\[grunt\] and use the grunt \[init task\]\[init\]._ @@ -106,21 +105,22 @@ The following is a transcript of the session in which this project and repository were created. This is not actually a part of the \[grunt\]\[grunt\] \"init:$template\" template, this session transcript was added afterwards. The text after the `$` are the commands that were executed, and everything else is -program output. If you want to see the repository exactly as it was created by -grunt, view \[the previous commit\]\[prev\].' > README.md\r" +program output. + +**If you want to see the repository exactly as it was created by grunt, \[view +the \"generated\" branch\]\[prev\].**' > README.md\r" expect "$ " send "echo -e ' -Want to learn more? Check \[grunt\]\[grunt\] out. -\[grunt\]: https://github.com/cowboy/grunt -\[issues\]: https://github.com/cowboy/grunt/issues -\[init\]: https://github.com/cowboy/grunt/blob/master/docs/task_init.md -\[expect\]: https://github.com/cowboy/grunt/blob/master/dev/init.exp -\[prev\]: https://github.com/cowboy/$project/tree/HEAD~1 +\[grunt\]: http://gruntjs.com/ +\[issues\]: https://github.com/gruntjs/grunt/issues +\[init\]: https://github.com/gruntjs/grunt/blob/master/docs/task_init.md +\[expect\]: https://github.com/gruntjs/grunt/blob/master/dev/init.exp +\[prev\]: https://github.com/gruntjs/$project/tree/generated Note that this entire build process is automated by a rather complex \[expect script\]\[expect\], which is used to automate grunt in order to facilitate the -creation of this and other \[init task\]\[init\] example repositories. +creation of this and other \[init task\]\[init\] sample repositories. ```' >> README.md\r" expect "$ " @@ -128,13 +128,12 @@ expect "$ " send "cat /tmp/grunt-expect-out | perl -ne's/ --no-color//;if(/^\\\$ mkdir/){\$x=1}elsif(/^\\\$ # EOF/){\$x=0}\$x&&print\$_' >> README.md\r" expect "$ " send "echo -e '``` - -## License -Copyright (c) 2012 \"Cowboy\" Ben Alman -Licensed under the MIT license.' >> README.md\r" +' >> README.md\r" # Commit again. expect "$ " +send "git branch generated\r" +expect "$ " send "git add .\r" expect "$ " send "git commit -m 'Adding project creation transcript.'\r" @@ -142,7 +141,7 @@ send "git commit -m 'Adding project creation transcript.'\r" # Push to GitHub. if {$gitpush} { expect "$ " - send "git push -uf origin master\r" + send "git push -uf --all origin\r" } expect "$ " diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/README.md b/node_modules/grunt-coffee/node_modules/grunt/docs/README.md index e46e672..517d703 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/README.md @@ -1 +1 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](/cowboy/grunt/blob/master/docs/toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](/gruntjs/grunt/blob/master/docs/toc.md) diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api.md index 9bb5509..32ef7c8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # The grunt API diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_config.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_config.md index 26eaf45..b475ad9 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_config.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_config.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.config diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_fail.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_fail.md index 91b5f79..29a6e17 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_fail.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_fail.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.fail diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_file.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_file.md index fb3ecec..303e6f4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_file.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_file.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.file diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_log.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_log.md index 770a876..72335f0 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_log.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_log.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.log, grunt.verbose diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_task.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_task.md index 8489214..a5a1d77 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_task.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_task.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.task @@ -266,7 +266,7 @@ _This method is also available as [grunt.helper](api.md)._ ## Directives Directives are essentially string placeholders for helper functions, specified as values in the [config object](getting_started.md). -A good example of directives would be the `` and `` directives in grunt's own [grunt.js gruntfile](../grunt.js). Or the `` and `` directives in the [sample jQuery plugin gruntfile](https://github.com/cowboy/grunt-jquery-example/blob/master/grunt.js). +A good example of directives would be the `` and `` directives in grunt's own [grunt.js gruntfile](../grunt.js). Or the `` and `` directives in the [sample jQuery plugin gruntfile](https://github.com/gruntjs/grunt-init-jquery-sample/blob/master/grunt.js). See the list of [built-in directives](helpers_directives.md) for examples. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_template.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_template.md index 03fd567..99810e9 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_template.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_template.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.template diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/api_utils.md b/node_modules/grunt-coffee/node_modules/grunt/docs/api_utils.md index bf3e643..78b0fe1 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/api_utils.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_utils.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # [The grunt API](api.md) / grunt.utils diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md b/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md index 7a2e1ca..ab5b1a9 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Contributing to grunt @@ -10,7 +10,7 @@ Join the [freenode](http://freenode.net/) #grunt IRC channel. We've got a bot an ## Filing issues -If something isn't working like you think it should, read the [API documentation](api.md). If it still isn't working like you think it should, [file an issue](https://github.com/cowboy/grunt/issues). If you'd like to chat directly, pop into IRC. +If something isn't working like you think it should, read the [API documentation](api.md). If it still isn't working like you think it should, [file an issue](https://github.com/gruntjs/grunt/issues). If you'd like to chat directly, pop into IRC. ## Cloning grunt diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/example_gruntfiles.md b/node_modules/grunt-coffee/node_modules/grunt/docs/example_gruntfiles.md index 4f65d2e..c6818f7 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/example_gruntfiles.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/example_gruntfiles.md @@ -1,12 +1,12 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Example gruntfiles Take a look at these example gruntfiles to see a few of the possible variations: -* [Sample jQuery plugin gruntfile](https://github.com/cowboy/grunt-jquery-example/blob/master/grunt.js) (as generated by the `init:jquery` task) -* [Sample CommonJS module gruntfile](https://github.com/cowboy/grunt-commonjs-example/blob/master/grunt.js) (as generated by the `init:commonjs` task) -* [Sample Node.js npm module gruntfile](https://github.com/cowboy/grunt-node-example/blob/master/grunt.js) (as generated by the `init:node` task) +* [Sample jQuery plugin gruntfile](https://github.com/gruntjs/grunt-init-jquery-sample/blob/master/grunt.js) (as generated by the `init:jquery` task) +* [Sample CommonJS module gruntfile](https://github.com/gruntjs/grunt-init-commonjs-sample/blob/master/grunt.js) (as generated by the `init:commonjs` task) +* [Sample Node.js npm module gruntfile](https://github.com/gruntjs/grunt-init-node-sample/blob/master/grunt.js) (as generated by the `init:node` task) * [grunt's gruntfile](../grunt.js) * [javascript-hooker's gruntfile](https://github.com/cowboy/javascript-hooker/blob/master/grunt.js) * [glob-whatev's gruntfile](https://github.com/cowboy/node-glob-whatev/blob/master/grunt.js) diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/exit_codes.md b/node_modules/grunt-coffee/node_modules/grunt/docs/exit_codes.md index 4a503f1..f980217 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/exit_codes.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/exit_codes.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Grunt exit codes diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md b/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md index d73d1f9..ef657a4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Frequently Asked Questions diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/getting_started.md b/node_modules/grunt-coffee/node_modules/grunt/docs/getting_started.md index f57b4e5..5b17cd5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/getting_started.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/getting_started.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Getting Started diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/helpers_directives.md b/node_modules/grunt-coffee/node_modules/grunt/docs/helpers_directives.md index 52bee47..fb816c3 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/helpers_directives.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/helpers_directives.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Helpers and Directives diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md b/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md index f0ee2c1..5201c40 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md @@ -1,8 +1,8 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # Plugins -This section is a work in progress. Grunt currently has preliminary plugin support, but it might be a little while before plugins work perfectly. If you have any suggestions or comments, please [file an issue](/cowboy/grunt/issues) and we'll work it all out! +This section is a work in progress. Grunt currently has preliminary plugin support, but it might be a little while before plugins work perfectly. If you have any suggestions or comments, please [file an issue](/gruntjs/grunt/issues) and we'll work it all out! ## Why create a grunt plugin? diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/task_concat.md b/node_modules/grunt-coffee/node_modules/grunt/docs/task_concat.md index 1853474..eb2ba9f 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/task_concat.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_concat.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # concat (built-in task) Concatenate one or more input files (and/or [directives](helpers_directives.md) output, like ``) into an output file. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/task_init.md b/node_modules/grunt-coffee/node_modules/grunt/docs/task_init.md index e81986f..885b114 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/task_init.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_init.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # init (built-in task) Generate project scaffolding from a predefined template. @@ -26,26 +26,26 @@ If your code is DOM-related, [QUnit unit tests](task_qunit.md) will be used, oth **You will most likely need to edit the generated grunt.js file before running `grunt`. If you run grunt after generating grunt.js, and it exits with errors, edit the grunt.js file!** -_See an [example repo](https://github.com/cowboy/grunt-gruntfile-example/tree/HEAD~1) generated by this template along with the [creation transcript](https://github.com/cowboy/grunt-gruntfile-example/blob/master/README.md)._ +_See an [example repo](https://github.com/gruntjs/grunt-init-gruntfile-sample/tree/generated) generated by this template along with the [creation transcript](https://github.com/gruntjs/grunt-init-gruntfile-sample#project-creation-transcript)._ ### commonjs Generated via `grunt init:commonjs`, this customizable template creates an entire project directory structure with a [grunt.js gruntfile](getting_started.md), Npm-friendly package.json file, sample [CommonJS](http://www.commonjs.org/) source file and Nodeunit unit tests. In addition, predefined [lint](task_lint.md), [concat](task_concat.md) and [minification](task_min.md) tasks are generated. -_See an [example repo](https://github.com/cowboy/grunt-commonjs-example/tree/HEAD~1) generated by this template along with the [creation transcript](https://github.com/cowboy/grunt-commonjs-example/blob/master/README.md)._ +_See an [example repo](https://github.com/gruntjs/grunt-init-commonjs-sample/tree/generated) generated by this template along with the [creation transcript](https://github.com/gruntjs/grunt-init-commonjs-sample#project-creation-transcript)._ ### jquery Generated via `grunt init:jquery`, this customizable template creates an entire project directory structure with a [grunt.js gruntfile](getting_started.md), [jQuery package.json](https://github.com/jquery/plugins.jquery.com/blob/master/docs/package.md) file, [jQuery](http://jquery.com/) plugin file and [QUnit unit tests](task_qunit.md). In addition, predefined [lint](task_lint.md), [concat](task_concat.md) and [minification](task_min.md) tasks are generated. -_See an [example repo](https://github.com/cowboy/grunt-jquery-example/tree/HEAD~1) generated by this template along with the [creation transcript](https://github.com/cowboy/grunt-jquery-example/blob/master/README.md)._ +_See an [example repo](https://github.com/gruntjs/grunt-init-jquery-sample/tree/generated) generated by this template along with the [creation transcript](https://github.com/gruntjs/grunt-init-jquery-sample#project-creation-transcript)._ ### node Generated via `grunt init:node`, this customizable template creates an entire project directory structure with a [grunt.js gruntfile](getting_started.md), Npm package.json file, sample [Node.js](http://nodejs.org/) source file and Nodeunit unit tests. -_See an [example repo](https://github.com/cowboy/grunt-node-example/tree/HEAD~1) generated by this template along with the [creation transcript](https://github.com/cowboy/grunt-node-example/blob/master/README.md)._ +_See an [example repo](https://github.com/gruntjs/grunt-init-node-sample/tree/generated) generated by this template along with the [creation transcript](https://github.com/gruntjs/grunt-init-node-sample#project-creation-transcript)._ ## Specifying default prompt answers Each init prompt either has a default value hard-coded or it looks at the current enviroment to attempt to determine that default value. If you want to override a particular prompt's default value, you can do so in the optional OS X or Linux `~/.grunt/tasks/init/defaults.json` or Windows `%USERPROFILE%\.grunt\tasks\init\defaults.json` file. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/task_lint.md b/node_modules/grunt-coffee/node_modules/grunt/docs/task_lint.md index ee67816..bb79a1a 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/task_lint.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_lint.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # lint (built-in task) Validate files with [JSHint][jshint]. @@ -108,7 +108,7 @@ grunt.initConfig({ ### Specifying JSHint options and globals -In this example, taken from the [Sample jQuery plugin gruntfile](https://github.com/cowboy/grunt-jquery-example/blob/master/grunt.js), custom JSHint `options` and `globals` are specified. These options are explained in the [JSHint documentation](http://www.jshint.com/options/). +In this example, taken from the [Sample jQuery plugin gruntfile](https://github.com/gruntjs/grunt-init-jquery-sample/blob/master/grunt.js), custom JSHint `options` and `globals` are specified. These options are explained in the [JSHint documentation](http://www.jshint.com/options/). _Note: config `jshint.options` and `jshint.globals` apply to the entire project, but can be overridden with per-file comments like `/*global exports:false*/`._ diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/task_min.md b/node_modules/grunt-coffee/node_modules/grunt/docs/task_min.md index 2784a08..c184cbd 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/task_min.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_min.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # min (built-in task) Minify files with [UglifyJS][uglify]. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/task_qunit.md b/node_modules/grunt-coffee/node_modules/grunt/docs/task_qunit.md index 564929a..855f5a9 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/task_qunit.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_qunit.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # qunit (built-in task) Run [QUnit][qunit] unit tests in a headless [PhantomJS][phantom] instance. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/task_server.md b/node_modules/grunt-coffee/node_modules/grunt/docs/task_server.md index d17011a..3ee0335 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/task_server.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_server.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) # server (built-in task) Start a static web server. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md b/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md index 2fd0263..a2a8778 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) +[Grunt homepage](https://github.com/gruntjs/grunt) # Documentation table of contents diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/types_of_tasks.md b/node_modules/grunt-coffee/node_modules/grunt/docs/types_of_tasks.md index 1819368..3a9f752 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/docs/types_of_tasks.md +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/types_of_tasks.md @@ -1,4 +1,4 @@ -[Grunt homepage](https://github.com/cowboy/grunt) | [Documentation table of contents](toc.md) +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) **Note: this document is a little out-of-date. You're better off starting with the "Creating Tasks" section of the [API documentation](api.md).** @@ -48,7 +48,7 @@ grunt.initConfig({ }); ``` -While it's probably most useful for you to check out the JavaScript source of the [built-in tasks](https://github.com/cowboy/grunt/tree/master/tasks), this example shows how you might define your own multi task: +While it's probably most useful for you to check out the JavaScript source of the [built-in tasks](https://github.com/gruntjs/grunt/tree/master/tasks), this example shows how you might define your own multi task: ```javascript /*global config:true, task:true*/ @@ -249,4 +249,4 @@ grunt.registerTask('foo', 'My "foo" task.', function() { }); ``` -Take a look at the [built-in tasks](https://github.com/cowboy/grunt/tree/master/tasks) for more examples. +Take a look at the [built-in tasks](https://github.com/gruntjs/grunt/tree/master/tasks) for more examples. diff --git a/node_modules/grunt-coffee/node_modules/grunt/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/grunt.js index 75d10a0..bd6958d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/grunt.js +++ b/node_modules/grunt-coffee/node_modules/grunt/grunt.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { @@ -15,7 +15,13 @@ module.exports = function(grunt) { all: ['test/**/*.js'] }, lint: { - all: ['grunt.js', 'lib/**/*.js', 'tasks/*.js', 'tasks/*/*.js', 'test/**/*.js'] + all: [ + 'grunt.js', + 'lib/**/*.js', + 'tasks/*.js', + 'tasks/*/*.js', + 'test/{grunt,tasks,util}/*.js' + ] }, watch: { scripts: { @@ -36,7 +42,8 @@ module.exports = function(grunt) { boss: true, eqnull: true, node: true, - es5: true + es5: true, + strict: false }, globals: {} } diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js index 0ded479..79b4f36 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Nodejs libs. diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/cli.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/cli.js index 4a8118b..2876c18 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/cli.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/cli.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/config.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/config.js index eeda6bc..134c115 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/config.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/config.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/fail.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/fail.js index dbd2f5f..45eb909 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/fail.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/fail.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); @@ -39,7 +39,7 @@ function writeln(e, mode) { // A fatal error occured. Abort immediately. fail.fatal = function(e, errcode) { writeln(e, 'fatal'); - process.reallyExit(typeof errcode === 'number' ? errcode : 1); + process.exit(typeof errcode === 'number' ? errcode : 1); }; // Keep track of error and warning counts. @@ -70,7 +70,7 @@ fail.warn = function(e, errcode) { } // Log and exit. grunt.log.writeln().fail('Aborted due to warnings.'); - process.reallyExit(typeof errcode === 'number' ? errcode : 2); + process.exit(typeof errcode === 'number' ? errcode : 2); } } }; diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/file.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/file.js index be662a5..4523cb1 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/file.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/file.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/help.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/help.js index d91aca5..6164af3 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/help.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/help.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); @@ -63,7 +63,7 @@ grunt.log.writeln().writelns( 'grunt plugins specified in the "grunt.js" gruntfile or via command-line ' + 'options.' + '\n\n' + - 'For more information, see https://github.com/cowboy/grunt' + 'For more information, see http://gruntjs.com/' ); process.exit(); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/log.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/log.js index 3557da9..f7be8a0 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/log.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/log.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/option.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/option.js index 50c19f0..197f6dc 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/option.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/option.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // The actual option data. diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/task.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/task.js index a9a9208..43ac8ad 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/task.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/task.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/template.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/template.js index 1d884ab..1d0786b 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/template.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/template.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ var grunt = require('../grunt'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/utils.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/utils.js index ea35df4..155c617 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/utils.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/utils.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Nodejs libs. diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/util/findup.js b/node_modules/grunt-coffee/node_modules/grunt/lib/util/findup.js index 71aee3d..c9f9444 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/util/findup.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/util/findup.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Nodejs libs. diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/util/namespace.js b/node_modules/grunt-coffee/node_modules/grunt/lib/util/namespace.js index 3b7f724..7127980 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/util/namespace.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/util/namespace.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ (function(exports) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/util/task.js b/node_modules/grunt-coffee/node_modules/grunt/lib/util/task.js index c3af258..398a605 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/lib/util/task.js +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/util/task.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ (function(exports) { @@ -41,16 +41,18 @@ // Error constructors. function TaskError(message) { - this.name = 'TaskError'; + Error.captureStackTrace(this, TaskError); this.message = message; } - TaskError.prototype = new Error(); + TaskError.prototype = Object.create(Error.prototype); + TaskError.prototype.name = 'TaskError'; function HelperError(message) { - this.name = 'HelperError'; + Error.captureStackTrace(this, HelperError); this.message = message; } - HelperError.prototype = new Error(); + HelperError.prototype = Object.create(Error.prototype); + HelperError.prototype.name = 'HelperError'; // Expose the ability to create a new taskError. Task.prototype.taskError = function(message, e) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/package.json index fe7473a..71e56fd 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/package.json @@ -25,6 +25,7 @@ "nodelint": ">0.0.0" }, "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.\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, forEach…) 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 async.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n });\n\n async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n async.parallel([\n function(){ ... },\n function(){ ... }\n ], callback);\n\n async.series([\n function(){ ... },\n function(){ ... }\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\n## Download\n\nReleases are available for download from\n[GitHub](http://github.com/caolan/async/downloads).\nAlternatively, you can install using Node Package Manager (npm):\n\n npm install async\n\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed\n\n__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped\n\n\n## In the Browser\n\nSo far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n \n \n\n\n## Documentation\n\n### Collections\n\n* [forEach](#forEach)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [until](#until)\n* [waterfall](#waterfall)\n* [queue](#queue)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\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\n### forEach(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 forEach 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 which must be called once it has completed.\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 // assuming openFiles is an array of file names and saveFile is a function\n // to save the modified contents of that file:\n\n async.forEach(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n\n---------------------------------------\n\n\n### forEachSeries(arr, iterator, callback)\n\nThe same as forEach 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\n### forEachLimit(arr, limit, iterator, callback)\n\nThe same as forEach only the iterator is applied to batches of items in the\narray, in series. The next batch of iterators is only called once the current\none has completed processing.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - How many items should be in each batch.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\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 // Assume documents is an array of JSON objects and requestApi is a\n // function that interacts with a rate-limited REST api.\n\n async.forEachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n---------------------------------------\n\n\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 which must be called once it has completed\n 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 async.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### 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\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 path.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 which must be called 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 async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n---------------------------------------\n\n\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\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as filter, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\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 its 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 which accepts an optional error as its first argument, and the state\n of the reduction as the second. If an error is passed to the callback, the\n reduction is stopped and the main callback is immediately called with the\n 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 async.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### 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\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 which must be called 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 async.detect(['file1','file2','file3'], path.exists, function(result){\n // result now equals the first file in the list that exists\n });\n\n---------------------------------------\n\n\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\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 which must be called once it has completed\n with an error (which can be null) and a value to use as the sort 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 async.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\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 path.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 which must be called 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 async.some(['file1','file2','file3'], path.exists, function(result){\n // if result is true then at least one of the files exists\n });\n\n---------------------------------------\n\n\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 path.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 which must be called 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 async.every(['file1','file2','file3'], path.exists, function(result){\n // if result is true then every file exists\n });\n\n---------------------------------------\n\n\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 which must be called once it has completed\n 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 async.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### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\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 it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.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\n function(err, results){\n // results is now equal to ['one', 'two']\n });\n\n\n // an example using an object instead of an array\n async.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 },\n function(err, results) {\n // results is now equal to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\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 a\n callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.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\n function(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\n async.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 },\n function(err, results) {\n // results is now equals to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\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 which must be called once it has completed with an optional\n error as the first 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 var count = 0;\n\n async.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\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\n\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 callback it\n must call on completion.\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 async.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\n\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.\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* 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 // create a queue object with concurrency 2\n\n var q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n }, 2);\n\n\n // assign a callback\n q.drain = function() {\n console.log('all items have been processed');\n }\n\n // add some items to the queue\n\n q.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n });\n q.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n });\n\n // add some items to the queue (batch-wise)\n\n q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n });\n\n\n---------------------------------------\n\n\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\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 syntax is easier to understand by looking at the example.\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. If all tasks complete\n successfully, it will receive an object containing their results.\n\n__Example__\n\n async.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\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n async.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 ],\n function(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 email_link: function(callback){\n // once the file is written let's email a link to it...\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\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. Its 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, each function is passed a callback it\n must call on completion.\n\n__Example__\n\n var iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n ]);\n\n node> var iterator2 = iterator();\n 'one'\n node> var iterator3 = iterator2();\n 'two'\n node> iterator3();\n 'three'\n node> var nextfn = iterator2.next();\n node> nextfn();\n 'three'\n\n\n---------------------------------------\n\n\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 // using apply\n\n async.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\n async.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n },\n ]);\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n node> var fn = async.apply(sys.puts, 'one');\n node> fn('two', 'three');\n one\n two\n three\n\n---------------------------------------\n\n\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 setTimeout(callback, 0),\nwhich means other higher priority events 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 var call_order = [];\n async.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two]\n });\n call_order.push('one')\n\n\n## Utils\n\n\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\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 var slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n };\n var fn = async.memoize(slow_fn);\n\n // fn can now be used as if it were slow_fn\n fn('some name', function () {\n // callback\n });\n\n\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\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 var hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n };\n\n node> async.log(hello, 'world');\n 'hello world'\n\n\n---------------------------------------\n\n\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 var hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n };\n\n node> async.dir(hello, 'world');\n {hello: 'world'}\n\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", + "readmeFilename": "README.md", "_id": "async@0.1.22", "_from": "async@~0.1.18" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/package.json index 780a678..4fda7d0 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/package.json @@ -14,6 +14,7 @@ }, "main": "colors", "readme": "# colors.js - get color and style in your node.js console ( and browser ) like what\n\n\n\n\n## Installation\n\n npm install colors\n\n## colors and styles!\n\n- bold\n- italic\n- underline\n- inverse\n- yellow\n- cyan\n- white\n- magenta\n- green\n- red\n- grey\n- blue\n- rainbow\n- zebra\n- random\n\n## Usage\n\n``` js\nvar colors = require('./colors');\n\nconsole.log('hello'.green); // outputs green text\nconsole.log('i like cake and pies'.underline.red) // outputs red underlined text\nconsole.log('inverse the color'.inverse); // inverses the color\nconsole.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces)\n```\n\n# Creating Custom themes\n\n```js\n\nvar require('colors');\n\ncolors.setTheme({\n silly: 'rainbow',\n input: 'grey',\n verbose: 'cyan',\n prompt: 'grey',\n info: 'green',\n data: 'grey',\n help: 'cyan',\n warn: 'yellow',\n debug: 'blue',\n error: 'red'\n});\n\n// outputs red text\nconsole.log(\"this is an error\".error);\n\n// outputs yellow text\nconsole.log(\"this is a warning\".warn);\n```\n\n\n### Contributors \n\nMarak (Marak Squires)\nAlexis Sellier (cloudhead)\nmmalecki (Maciej Małecki)\nnicoreed (Nico Reed)\nmorganrallen (Morgan Allen)\nJustinCampbell (Justin Campbell)\nded (Dustin Diaz)\n\n\n#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded)\n", + "readmeFilename": "ReadMe.md", "_id": "colors@0.6.0-1", "_from": "colors@~0.6.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/connect.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/connect.js index 5557636..19b4502 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/connect.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/connect.js @@ -29,7 +29,7 @@ exports = module.exports = createServer; * Framework version. */ -exports.version = '2.4.5'; +exports.version = '2.4.6'; /** * Expose mime module. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/package.json index 05f17ec..b284b09 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/package.json @@ -19,6 +19,7 @@ } }, "readme": "# node-bytes\n\n Byte string parser / formatter.\n\n## Example:\n\n```js\nbytes('1kb')\n// => 1024\n\nbytes('2mb')\n// => 2097152\n\nbytes('1gb')\n// => 1073741824\n\nbytes(1073741824)\n// => 1gb\n```\n\n## Installation\n\n```\n$ npm install bytes\n$ component install visionmedia/bytes.js\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\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", "_id": "bytes@0.1.0", "_from": "bytes@0.1.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/package.json index b82d023..e169b94 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/package.json @@ -27,6 +27,7 @@ "node": "*" }, "readme": "# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #\n\ncookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.\n\nSee [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.\n\n## how?\n\n```\nnpm install cookie\n```\n\n```javascript\nvar cookie = require('cookie');\n\nvar hdr = cookie.serialize('foo', 'bar');\n// hdr = 'foo=bar';\n\nvar cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');\n// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };\n```\n\n## more\n\nThe serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.\n\n### path\n> cookie path\n\n### expires\n> absolute expiration date for the cookie (Date object)\n\n### maxAge\n> relative max age of the cookie from when the client receives it (seconds)\n\n### domain\n> domain for the cookie\n\n### secure\n> true or false\n\n### httpOnly\n> true or false\n\n", + "readmeFilename": "README.md", "_id": "cookie@0.0.4", "_from": "cookie@0.0.4" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/package.json index 093f6ec..b16c89e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/package.json @@ -19,6 +19,7 @@ "url": "git://github.com/alexgorbatchev/node-crc.git" }, "readme": "# JavaScript CRC 8, 16 and 32.\n\nThis is a basic port/copy of the JavaScript CRC implementation. The module works with any CommonJS system supporting `module.exports` notation as well as in the browser. When loaded in the browser, all functions end up under the `window.crc` \"namespace\".\n\nOriginal code is taken from http://www.digsys.se/JavaScript/CRC.aspx \n\n## Functions\n\nThe following functions are implemented:\n\n crc8(String)\t#=> Number\n crcArc(String)\t#=> Number\n crc16(String)\t#=> Number\n fcs16(String)\t#=> Number\n crc32(String)\t#=> Number\n hex8(Number)\t#=> String\n hex16(Number)\t#=> String\n hex32(Number)\t#=> String\n\n## Installation\n\n\tgit clone git://github.com/alexgorbatchev/node-crc.git\n\nor\n\n npm install crc\n\n## Running tests\n\n $ npm install\n $ make test", + "readmeFilename": "README.md", "_id": "crc@0.2.0", "_from": "crc@0.2.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/package.json index 3906600..abc581e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/package.json @@ -26,6 +26,7 @@ } }, "readme": "\n# debug\n\n tiny node.js debugging utility.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Example\n\n This module is modelled after node core's debugging technique, allowing you to enable one or more topic-specific debugging functions, for example core does the following within many modules:\n\n```js\nvar debug;\nif (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) {\n debug = function(x) {\n var prefix = process.pid + ',' +\n (process.env.NODE_WORKER_ID ? 'Worker' : 'Master');\n console.error(prefix, x);\n };\n} else {\n debug = function() { };\n}\n```\n\n This concept is extremely simple but it works well. 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 stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\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 <tj@vision-media.ca>\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", "_id": "debug@0.7.0", "_from": "debug@*" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/package.json index 6d368f3..1fd45c7 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/package.json @@ -21,6 +21,7 @@ }, "optionalDependencies": {}, "readme": "# Formidable\n\n[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)\n\n## Purpose\n\nA node.js module for parsing form data, especially file uploads.\n\n## Current status\n\nThis module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading\nand encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from\na large variety of clients and is considered production-ready.\n\n## Features\n\n* Fast (~500mb/sec), non-buffering multipart parser\n* Automatically writing file uploads to disk\n* Low memory footprint\n* Graceful error handling\n* Very high test coverage\n\n## Changelog\n\n### v1.0.9\n\n* Emit progress when content length header parsed (Tim Koschützki)\n* Fix Readme syntax due to GitHub changes (goob)\n* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)\n\n### v1.0.8\n\n* Strip potentially unsafe characters when using `keepExtensions: true`.\n* Switch to utest / urun for testing\n* Add travis build\n\n### v1.0.7\n\n* Remove file from package that was causing problems when installing on windows. (#102)\n* Fix typos in Readme (Jason Davies).\n\n### v1.0.6\n\n* Do not default to the default to the field name for file uploads where\n filename=\"\".\n\n### v1.0.5\n\n* Support filename=\"\" in multipart parts\n* Explain unexpected end() errors in parser better\n\n**Note:** Starting with this version, formidable emits 'file' events for empty\nfile input fields. Previously those were incorrectly emitted as regular file\ninput fields with value = \"\".\n\n### v1.0.4\n\n* Detect a good default tmp directory regardless of platform. (#88)\n\n### v1.0.3\n\n* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)\n* Small performance improvements\n* New test suite and fixture system\n\n### v1.0.2\n\n* Exclude node\\_modules folder from git\n* Implement new `'aborted'` event\n* Fix files in example folder to work with recent node versions\n* Make gently a devDependency\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)\n\n### v1.0.1\n\n* Fix package.json to refer to proper main directory. (#68, Dean Landolt)\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)\n\n### v1.0.0\n\n* Add support for multipart boundaries that are quoted strings. (Jeff Craig)\n\nThis marks the beginning of development on version 2.0 which will include\nseveral architectural improvements.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)\n\n### v0.9.11\n\n* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)\n* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class\n\n**Important:** The old property names of the File class will be removed in a\nfuture release.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)\n\n### Older releases\n\nThese releases were done before starting to maintain the above Changelog:\n\n* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)\n* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)\n* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)\n* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)\n* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)\n* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)\n* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)\n* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)\n* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)\n* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)\n\n## Installation\n\nVia [npm](http://github.com/isaacs/npm):\n\n npm install formidable@latest\n\nManually:\n\n git clone git://github.com/felixge/node-formidable.git formidable\n vim my.js\n # var formidable = require('./formidable');\n\nNote: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.\n\n## Example\n\nParse an incoming file upload.\n\n var formidable = require('formidable'),\n http = require('http'),\n\n util = require('util');\n\n http.createServer(function(req, res) {\n if (req.url == '/upload' && req.method.toLowerCase() == 'post') {\n // parse a file upload\n var form = new formidable.IncomingForm();\n form.parse(req, function(err, fields, files) {\n res.writeHead(200, {'content-type': 'text/plain'});\n res.write('received upload:\\n\\n');\n res.end(util.inspect({fields: fields, files: files}));\n });\n return;\n }\n\n // show a file upload form\n res.writeHead(200, {'content-type': 'text/html'});\n res.end(\n '
'+\n '
'+\n '
'+\n ''+\n '
'\n );\n }).listen(80);\n\n## API\n\n### formidable.IncomingForm\n\n__new formidable.IncomingForm()__\n\nCreates a new incoming form.\n\n__incomingForm.encoding = 'utf-8'__\n\nThe encoding to use for incoming form fields.\n\n__incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()__\n\nThe directory for placing file uploads in. You can move them later on using\n`fs.rename()`. The default directory is picked at module load time depending on\nthe first existing directory from those listed above.\n\n__incomingForm.keepExtensions = false__\n\nIf you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`.\n\n__incomingForm.type__\n\nEither 'multipart' or 'urlencoded' depending on the incoming request.\n\n__incomingForm.maxFieldsSize = 2 * 1024 * 1024__\n\nLimits the amount of memory a field (not file) can allocate in bytes.\nIf this value is exceeded, an `'error'` event is emitted. The default\nsize is 2MB.\n\n__incomingForm.hash = false__\n\nIf you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.\n\n__incomingForm.bytesReceived__\n\nThe amount of bytes received for this form so far.\n\n__incomingForm.bytesExpected__\n\nThe expected number of bytes in this form.\n\n__incomingForm.parse(request, [cb])__\n\nParses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:\n\n incomingForm.parse(req, function(err, fields, files) {\n // ...\n });\n\n__incomingForm.onPart(part)__\n\nYou may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.\n\n incomingForm.onPart = function(part) {\n part.addListener('data', function() {\n // ...\n });\n }\n\nIf you want to use formidable to only handle certain parts for you, you can do so:\n\n incomingForm.onPart = function(part) {\n if (!part.filename) {\n // let formidable handle all non-file parts\n incomingForm.handlePart(part);\n }\n }\n\nCheck the code in this method for further inspiration.\n\n__Event: 'progress' (bytesReceived, bytesExpected)__\n\nEmitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.\n\n__Event: 'field' (name, value)__\n\nEmitted whenever a field / value pair has been received.\n\n__Event: 'fileBegin' (name, file)__\n\nEmitted whenever a new file is detected in the upload stream. Use this even if\nyou want to stream the file to somewhere else while buffering the upload on\nthe file system.\n\n__Event: 'file' (name, file)__\n\nEmitted whenever a field / file pair has been received. `file` is an instance of `File`.\n\n__Event: 'error' (err)__\n\nEmitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.\n\n__Event: 'aborted'__\n\nEmitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).\n\n__Event: 'end' ()__\n\nEmitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.\n\n### formidable.File\n\n__file.size = 0__\n\nThe size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.\n\n__file.path = null__\n\nThe path this file is being written to. You can modify this in the `'fileBegin'` event in\ncase you are unhappy with the way formidable generates a temporary path for your files.\n\n__file.name = null__\n\nThe name this file had according to the uploading client.\n\n__file.type = null__\n\nThe mime type of this file, according to the uploading client.\n\n__file.lastModifiedDate = null__\n\nA date object (or `null`) containing the time this file was last written to. Mostly\nhere for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).\n\n__file.hash = null__\n\nIf hash calculation was set, you can read the hex digest out of this var.\n\n## License\n\nFormidable is licensed under the MIT license.\n\n## Ports\n\n* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable\n\n## Credits\n\n* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js\n", + "readmeFilename": "Readme.md", "_id": "formidable@1.0.11", "description": "[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)", "_from": "formidable@1.0.11" diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/package.json index e1f985e..d9fddb2 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/package.json @@ -14,6 +14,7 @@ "should": "*" }, "readme": "\n# node-fresh\n\n HTTP response freshness testing\n\n## fresh(req, res)\n\n Check freshness of `req` and `res` headers.\n\n When the cache is \"fresh\" __true__ is returned,\n otherwise __false__ is returned to indicate that\n the cache is now stale.\n\n## Example:\n\n```js\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'luna' };\nfresh(req, res);\n// => false\n\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'tobi' };\nfresh(req, res);\n// => true\n```\n\n## Installation\n\n```\n$ npm install fresh\n```", + "readmeFilename": "Readme.md", "_id": "fresh@0.1.0", "_from": "fresh@0.1.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/package.json index 1b66942..73cfe40 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/package.json @@ -14,6 +14,7 @@ }, "main": "index", "readme": "\n# pause\n\n Pause streams...\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\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", "_id": "pause@0.0.1", "_from": "pause@0.0.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/History.md index 3eaf7df..1feef45 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/History.md +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/History.md @@ -1,4 +1,14 @@ +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 ================== diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Makefile index e4df837..0a21cf7 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Makefile +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Makefile @@ -1,5 +1,12 @@ +test/browser/qs.js: querystring.js + component build package.json test/browser/qs + +querystring.js: lib/head.js lib/querystring.js lib/tail.js + cat $^ > $@ + test: - @./node_modules/.bin/mocha + @./node_modules/.bin/mocha \ + --ui bdd .PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Readme.md index db0d145..27e54a4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Readme.md +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Readme.md @@ -1,6 +1,6 @@ # node-querystring - query string parser for node 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. + 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 @@ -28,6 +28,10 @@ and execute: $ make test +browser: + + $ open test/browser/index.html + ## License (The MIT License) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/component.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/component.json new file mode 100644 index 0000000..ba34ead --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/component.json @@ -0,0 +1,6 @@ +{ + "name": "querystring", + "description": "Querystring parser / stringifier with nesting support", + "keywords": ["querystring", "query", "parser"], + "main": "lib/querystring.js" +} \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/head.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/head.js new file mode 100644 index 0000000..55d3817 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/head.js @@ -0,0 +1 @@ +;(function(){ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/querystring.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/querystring.js index 6c72712..d3689bb 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/querystring.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/querystring.js @@ -1,16 +1,4 @@ -/*! - * querystring - * Copyright(c) 2010 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Library version. - */ - -exports.version = '0.4.2'; - /** * Object#toString() ref for stringify(). */ @@ -111,12 +99,6 @@ 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) @@ -126,7 +108,7 @@ function parseString(str){ // ?foo if ('' == key) key = pair, val = ''; - return merge(ret, key, val); + return merge(ret, decode(key), decode(val)); }, { base: {} }).base; } @@ -192,7 +174,7 @@ 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 + '[]')); + ret.push(stringify(arr[i], prefix + '['+i+']')); } return ret.join('&'); } @@ -262,3 +244,19 @@ function lastBraceInKey(str) { 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; + } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/tail.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/tail.js new file mode 100644 index 0000000..158693a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/tail.js @@ -0,0 +1 @@ +})(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/package.json index 8a8ee65..233d5e4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/package.json @@ -1,14 +1,24 @@ { "name": "qs", "description": "querystring parser", - "version": "0.4.2", + "version": "0.5.1", + "keywords": [ + "query string", + "parser", + "component" + ], "repository": { "type": "git", "url": "git://github.com/visionmedia/node-querystring.git" }, "devDependencies": { "mocha": "*", - "should": "*" + "expect.js": "*" + }, + "component": { + "scripts": { + "querystring": "querystring.js" + } }, "author": { "name": "TJ Holowaychuk", @@ -19,7 +29,8 @@ "engines": { "node": "*" }, - "readme": "# node-querystring\n\n query string parser for node 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\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\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.", - "_id": "qs@0.4.2", - "_from": "qs@0.4.2" + "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 <tj@vision-media.ca>\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", + "_id": "qs@0.5.1", + "_from": "qs@0.5.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/querystring.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/querystring.js new file mode 100644 index 0000000..7466b06 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/querystring.js @@ -0,0 +1,254 @@ +;(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; + } +} +})(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/expect.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/expect.js new file mode 100644 index 0000000..76aa4e8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/expect.js @@ -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= 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 : {} +); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/index.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/index.html new file mode 100644 index 0000000..c73147a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/index.html @@ -0,0 +1,18 @@ + + + Mocha + + + + + + + + + + + + +
+ + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/jquery.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/jquery.js new file mode 100644 index 0000000..f3201aa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/test/browser/jquery.js @@ -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 = "
a"; + + 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 = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
t
"; + 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 = ""; + + // 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 = ""; + + 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 = "

"; + + // 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 = "
"; + + // 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 = /", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and \n\n```\n\nIn the browser, you can attach Hooker's methods to any object.\n\n```html\n\n\n\n```\n\n## Documentation\n\n### hooker.hook\nMonkey-patch (hook) one or more methods of an object.\n#### Signature:\n`hooker.hook(object, [ props, ] [options | prehookFunction])`\n#### `props`\nThe optional `props` argument can be a method name, array of method names or null. If null (or omitted), all enumerable methods of `object` will be hooked.\n#### `options`\n* `pre` - (Function) a pre-hook function to be executed before the original function. Arguments passed into the method will be passed into the pre-hook function as well.\n* `post` - (Function) a post-hook function to be executed after the original function. The original function's result is passed into the post-hook function as its first argument, followed by the method arguments.\n* `once` - (Boolean) if true, auto-unhook the function after the first execution.\n* `passName` - (Boolean) if true, pass the name of the method into the pre-hook function as its first arg (preceding all other arguments), and into the post-hook function as the second arg (after result but preceding all other arguments).\n\n#### Returns:\nAn array of hooked method names.\n\n### hooker.unhook\nUn-monkey-patch (unhook) one or more methods of an object.\n#### Signature:\n`hooker.unhook(object [, props ])`\n#### `props`\nThe optional `props` argument can be a method name, array of method names or null. If null (or omitted), all methods of `object` will be unhooked.\n#### Returns:\nAn array of unhooked method names.\n\n### hooker.orig\nGet a reference to the original method from a hooked function.\n#### Signature:\n`hooker.orig(object, props)`\n\n### hooker.override\nWhen a pre- or post-hook returns the result of this function, the value\npassed will be used in place of the original function's return value. Any\npost-hook override value will take precedence over a pre-hook override value.\n#### Signature:\n`hooker.override(value)`\n\n### hooker.preempt\nWhen a pre-hook returns the result of this function, the value passed will\nbe used in place of the original function's return value, and the original\nfunction will NOT be executed.\n#### Signature:\n`hooker.preempt(value)`\n\n### hooker.filter\nWhen a pre-hook returns the result of this function, the context and\narguments passed will be applied into the original function.\n#### Signature:\n`hooker.filter(context, arguments)`\n\n\n## Examples\nSee the unit tests for more examples.\n\n```javascript\nvar hooker = require('hooker');\n// Simple logging.\nhooker.hook(Math, \"max\", function() {\n console.log(arguments.length + \" arguments passed\");\n});\nMath.max(5, 6, 7) // logs: \"3 arguments passed\", returns 7\n\nhooker.unhook(Math, \"max\"); // (This is assumed between all further examples)\nMath.max(5, 6, 7) // 7\n\n// Returning hooker.override(value) overrides the original value.\nhooker.hook(Math, \"max\", function() {\n if (arguments.length === 0) {\n return hooker.override(9000);\n }\n});\nMath.max(5, 6, 7) // 7\nMath.max() // 9000\n\n// Auto-unhook after one execution.\nhooker.hook(Math, \"max\", {\n once: true,\n pre: function() {\n console.log(\"Init something here\");\n }\n});\nMath.max(5, 6, 7) // logs: \"Init something here\", returns 7\nMath.max(5, 6, 7) // 7\n\n// Filter `this` and arguments through a pre-hook function.\nhooker.hook(Math, \"max\", {\n pre: function() {\n var args = [].map.call(arguments, function(num) {\n return num * 2;\n });\n return hooker.filter(this, args); // thisValue, arguments\n }\n});\nMath.max(5, 6, 7) // 14\n\n// Modify the original function's result with a post-hook function.\nhooker.hook(Math, \"max\", {\n post: function(result) {\n return hooker.override(result * 100);\n }\n});\nMath.max(5, 6, 7) // 700\n\n// Hook every Math method. Note: if Math's methods were enumerable, the second\n// argument could be omitted. Since they aren't, an array of properties to hook\n// must be explicitly passed. Non-method properties will be skipped.\n// See a more generic example here: http://bit.ly/vvJlrS\nhooker.hook(Math, Object.getOwnPropertyNames(Math), {\n passName: true,\n pre: function(name) {\n console.log(\"=> Math.\" + name, [].slice.call(arguments, 1));\n },\n post: function(result, name) {\n console.log(\"<= Math.\" + name, result);\n }\n});\n\nvar result = Math.max(5, 6, 7);\n// => Math.max [ 5, 6, 7 ]\n// <= Math.max 7\nresult // 7\n\nresult = Math.ceil(3.456);\n// => Math.ceil [ 3.456 ]\n// <= Math.ceil 4\nresult // 4\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](https://github.com/cowboy/grunt).\n\n_Also, please don't edit files in the \"dist\" subdirectory as they are generated via grunt. You'll find source code in the \"lib\" subdirectory!_\n\n## Release History\n2012/01/09 - v0.2.3 - First official release.\n\n## License\nCopyright (c) 2012 \"Cowboy\" Ben Alman \nLicensed under the MIT license. \n\n", + "readmeFilename": "README.md", "_id": "hooker@0.2.3", "_from": "hooker@~0.2.3" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/HELP b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/HELP deleted file mode 100644 index e5738de..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/HELP +++ /dev/null @@ -1,9 +0,0 @@ -Usage: jshint path path2 [options] - -Options: - - --version display package version - --config custom config file - --reporter custom reporter - --jslint-reporter use a jslint compatible xml reporter - --show-non-errors show additional data generated by jshint diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/README.md index 2b5c1b0..ac1ee12 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/README.md @@ -10,9 +10,7 @@ To use jshint from any location (for npm v1.x) you need to install using the glo ## Usage -The command line interface looks like this. - - jshint path path2 [options] + jshint -h You can also require JSHint itself as a module. @@ -40,27 +38,44 @@ Show additional non-error data generated by jshint (unused globals etc). --show-non-errors -## Custom Options +## Configuration Options + +**Note:** This behavior described below is very different from versions prior to `0.6`. + +The CLI uses the default options that come with JSHint. + +Only one extra option is unique to node-jshint: `globals` +allows you to define an object of globals that get ignored for every file. +To see an example you can look at how whitelisted globals are defined +in the [jshint code](https://github.com/jshint/jshint/blob/c047ea1b01097fcc220fcd1a55c41f67ae2e6e81/jshint.js#L556) + +To have your own configuration apply, there are several methods you can use: -Specify custom lint options (see [example/config.json](https://github.com/jshint/node-jshint/blob/master/example/config.json)). +### Specify Manually - --config path/to/config.json +Setting the `--config=/path/to/your/config` command line option to specify your own configuration file outside of the directory tree for your project. -Note: This bypasses any .jshintrc files. +### Within your Project's Directory Tree -## Default Options +When the CLI is called, and a configuration file isn't specified already, `node-jshint` will attempt to locate one for you starting in `pwd`. (or "present working directory") If this does not yield a `.jshintrc` file, it will move one level up (`..`) the directory tree all the way up to the filesystem root. If a file is found, it stops immediately and uses that set of configuration. -The CLI uses the default options that come with JSHint. However, if it locates a .jshintrc file in your home directory (~/) it will use those options first. +This setup allows you to set up **one** configuration file for your entire project. (place it in the root folder) As long as you run `jshint` from anywhere within your project directory tree, the same configuration file will be used. -## Per Directory Options +### Home Directory -If there is a .jshintrc file in the current working directory, any of those options will take precedence over (or be merged with) any options found in the ~/.jshintrc file (if it exists). +If all the methods above do not yield a `.jshintrc` to use, the last place that will be checked is your user's `$HOME` directory. + +## File Extensions + +Default extension for files is ".js". If you want to use JSHint with other file extensions (.json), you need to pass this extra extension as an option : + + --extra-ext .json ## Ignoring Files and Directories -If there is a .jshintignore file in the current working directory, then any directories or files will be skipped over. +If there is a .jshintignore file in your project's directory tree, (also provided you run `jshint` from within your project's directory) then any directories or files specified will be skipped over. (behaves just like a `.gitignore` file) -Note: Pattern matching uses minimatch, with the nocase [option](https://github.com/isaacs/minimatch). When there is no match, it performs a left side match (when no forward slashes present and path is a directory). +**Note:** Pattern matching uses minimatch, with the nocase [option](https://github.com/isaacs/minimatch). When there is no match, it performs a left side match (when no forward slashes present and path is a directory). ## Installing dependencies for development @@ -69,3 +84,8 @@ Note: Pattern matching uses minimatch, with the nocase [option](https://github.c ## Build Commands jake -T + +## Project Guidelines + +* All tests are passing. +* No (new) JSHint errors are introduced. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/cli.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/cli.js index 2cf5fe7..14d6ed4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/cli.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/cli.js @@ -1,6 +1,6 @@ var fs = require('fs'), path = require('path'), - argsparser = require('argsparser'), + cli = require('cli').enable('glob', 'help'), hint = require('./hint'); function existsSync() { @@ -8,42 +8,62 @@ function existsSync() { return obj.existsSync.apply(obj, arguments); } -function _help() { - process.stdout.write(fs.readFileSync(__dirname + "/../HELP", "utf-8")); -} - -function _version() { - process.stdout.write(JSON.parse(fs.readFileSync(__dirname + "/../package.json", "utf-8")).version + "\n"); -} - function _removeJsComments(str) { str = str || ''; - str = str.replace(/\/\*[\s\S]*(?:\*\/)/g, ''); //everything between "/* */" + + // replace everything between "/* */" in a non-greedy way + // The English version of the regex is: + // match '/*' + // then match 0 or more instances of any character (including newlines) + // except for instances of '*/' + // then match '*/' + str = str.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, ''); + str = str.replace(/\/\/[^\n\r]*/g, ''); //everything after "//" return str; } function _loadAndParseConfig(filePath) { - return existsSync(filePath) ? + return filePath && existsSync(filePath) ? JSON.parse(_removeJsComments(fs.readFileSync(filePath, "utf-8"))) : {}; } -function _mergeConfigs(homerc, cwdrc) { - var homeConfig = _loadAndParseConfig(homerc), - cwdConfig = _loadAndParseConfig(cwdrc), - prop; - - for (prop in cwdConfig) { - if (typeof prop === 'string') { - if (prop === 'predef') { - homeConfig.predef = (homeConfig.predef || []).concat(cwdConfig.predef); - } else { - homeConfig[prop] = cwdConfig[prop]; - } - } +/** + * This function searches for a file with a specified name, it starts + * with the dir passed, and traverses up the filesystem until it either + * finds the file, or hits the root + * + * @param {String} name Filename to search for (.jshintrc, .jshintignore) + * @param {String} dir Defaults to process.cwd() + */ +function _searchFile(name, dir) { + dir = dir || process.cwd(); + + var filename = path.normalize(path.join(dir, name)), + parent = path.resolve(dir, ".."); + + if (existsSync(filename)) { + return filename; } - return homeConfig; + return dir === parent ? null : _searchFile(name, parent); +} + +function _findConfig() { + var name = ".jshintrc", + projectConfig = _searchFile(name), + homeConfig = path.normalize(path.join(process.env.HOME, name)); + + if (projectConfig) { + return projectConfig; + } + + // if no project config, check $HOME + if (existsSync(homeConfig)) { + return homeConfig; + } + + return false; } function _print(results) { @@ -66,56 +86,52 @@ function _print(results) { module.exports = { interpret: function (args) { - var config, reporter, ignore, - options = argsparser.parse(args), - pathsToIgnore = path.join(process.cwd(), '.jshintignore'), - defaultConfig = path.join(process.env.HOME, '.jshintrc'), - projectConfig = path.join(process.cwd(), '.jshintrc'), - customConfig = options["--config"], - customReporter = options["--reporter"] ? path.resolve(process.cwd(), options["--reporter"]) : null, - targets = options.node; - - //could be on Windows which we are looking for an attribute ending in 'node.exe' - if (targets === undefined) { - (function () { - var arg; - - for (arg in options) { - if (path.basename(arg) === 'node.exe') { - targets = options[arg]; - break; - } - } - }()); - } - - targets = typeof targets === "string" ? null : targets.slice(1); - - - if (options["--version"]) { - _version(); + var config, reporter, options, + customConfig, customReporter, + ignoreFile, ignores, extraExtensionList; + + cli.setArgv(args); + cli.options = {}; + options = cli.parse({ + 'version': ['v', 'display package version', 'boolean', false], + 'config': ['config', 'custom config file', 'string', false], + 'reporter': ['reporter', 'custom reporter', 'string', undefined], + 'jslint-reporter': ['jslint-reporter', 'use a jslint compatible xml reporter'], + 'checkstyle-reporter': ['checkstyle-reporter', 'use a CheckStyle compatible xml reporter'], + 'show-non-errors': ['show-non-errors', 'show additional data generated by jshint'], + 'extra-ext': ['extra-ext', 'comma-separated list of file extensions to use (.js is default)', 'string', ''] + }); + + customConfig = options.config; + customReporter = options.reporter ? path.resolve(process.cwd(), options.reporter) : null; + extraExtensionList = options["extra-ext"]; + + if (options.version) { + cli.setApp(path.resolve(__dirname + "/../package.json")); + process.stdout.write(cli.version + "\n"); return; } - if (!targets || options["--help"]) { - _help(); + if (options.help || !cli.args.length) { + cli.getUsage(); + process.exit(); return; } - if (options["--jslint-reporter"]) { + if (options['jslint-reporter']) { customReporter = "./reporters/jslint_xml.js"; } - if (options["--show-non-errors"]) { - customReporter = "./reporters/non_error.js"; + if (options['checkstyle-reporter']) { + customReporter = "./reporters/checkstyle.js"; } - if (customConfig) { - config = _loadAndParseConfig(customConfig); - } else { - config = _mergeConfigs(defaultConfig, projectConfig); + if (options['show-non-errors']) { + customReporter = "./reporters/non_error.js"; } + config = _loadAndParseConfig(customConfig ? customConfig : _findConfig()); + if (customReporter) { try { reporter = require(customReporter).reporter; @@ -126,15 +142,18 @@ module.exports = { } } - if (existsSync(pathsToIgnore)) { - ignore = fs.readFileSync(pathsToIgnore, "utf-8").split("\n").map(function (line) { - return line.trim(); - }).filter(function (line) { - return !!line; - }); + ignoreFile = _searchFile(".jshintignore"); + + if (ignoreFile) { + ignores = fs.readFileSync(ignoreFile, "utf8").split("\n") + .filter(function (line) { + return !!line.trim(); + }) + .map(function (line) { + return path.resolve(path.dirname(ignoreFile), line.trim()); + }); } - _print(hint.hint(targets, config, reporter, ignore)); + _print(hint.hint(cli.args, config, reporter, ignores, extraExtensionList)); } }; - diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/hint.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/hint.js index 5e4861b..0ecbbe8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/hint.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/hint.js @@ -9,8 +9,15 @@ var fs = require('fs'), function _lint(file, results, config, data) { var buffer, + globals, lintdata; + // config may be a pointer, but we modify it below, which changes it the next time it is used. + config = !config ? {} : Object.keys(config).reduce(function (obj, key) { + obj[key] = config[key]; + return obj; + }, {}); + try { buffer = fs.readFileSync(file, 'utf-8'); } catch (e) { @@ -21,7 +28,13 @@ function _lint(file, results, config, data) { // Remove potential Unicode Byte Order Mark. buffer = buffer.replace(/^\uFEFF/, ''); - if (!jshint.JSHINT(buffer, config)) { + // remove custom node-jshint option + if (config.globals) { + globals = config.globals; + delete config.globals; + } + + if (!jshint.JSHINT(buffer, config, globals)) { jshint.JSHINT.errors.forEach(function (error) { if (error) { results.push({file: file, error: error}); @@ -58,10 +71,11 @@ function isDirectory(aPath) { function _shouldIgnore(somePath, ignore) { function isIgnored(p) { var fnmatch = minimatch(somePath, p, {nocase: true}), + absmatch = path.resolve(somePath) === p, lsmatch = isDirectory(p) && p.match(/^[^\/]*\/?$/) && somePath.match(new RegExp("^" + p + ".*")); - return !!(fnmatch || lsmatch); + return !!(fnmatch || lsmatch || absmatch); } return ignore.some(function (ignorePath) { @@ -69,28 +83,31 @@ function _shouldIgnore(somePath, ignore) { }); } -function _collect(filePath, files, ignore) { +function _collect(filePath, files, ignore, regExtension) { if (ignore && _shouldIgnore(filePath, ignore)) { return; } - if (fs.statSync(filePath).isDirectory()) { fs.readdirSync(filePath).forEach(function (item) { - _collect(path.join(filePath, item), files, ignore); + _collect(path.join(filePath, item), files, ignore, regExtension); }); - } else if (filePath.match(/\.js$/)) { + } else if (filePath.match(regExtension)) { files.push(filePath); } } module.exports = { - hint: function (targets, config, reporter, ignore) { + hint: function (targets, config, reporter, ignore, extraExtensionList) { var files = [], results = [], - data = []; + data = [], + regExtension; + + extraExtensionList = extraExtensionList || ""; + regExtension = new RegExp('\\.(js' + (extraExtensionList === "" ? "" : "|" + extraExtensionList.replace(/,/g, "|").replace(/[\. ]/g, "")) + ")$"); targets.forEach(function (target) { - _collect(target, files, ignore); + _collect(target, files, ignore, regExtension); }); files.forEach(function (file) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/checkstyle.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/checkstyle.js new file mode 100644 index 0000000..0b2f6e1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/checkstyle.js @@ -0,0 +1,107 @@ +// Author: Boy Baukema +// http://github.com/relaxnow +module.exports = +{ + reporter: function (results, data) + { + "use strict"; + + var files = {}, + out = [], + pairs = { + "&": "&", + '"': """, + "'": "'", + "<": "<", + ">": ">" + }, + file, fileName, i, issue, globals, unuseds; + + function encode(s) { + for (var r in pairs) { + if (typeof(s) !== "undefined") { + s = s.replace(new RegExp(r, "g"), pairs[r]); + } + } + return s || ""; + } + + results.forEach(function (result) { + // Register the file + result.file = result.file.replace(/^\.\//, ''); + if (!files[result.file]) { + files[result.file] = []; + } + + // Add the error + files[result.file].push({ + severity: 'error', + line: result.error.line, + column: result.error.character, + message: result.error.reason, + source: result.error.raw + }); + }); + + data.forEach(function (result) { + file = data.file; + globals = result.implieds; + unuseds = result.unused; + + // Register the file + result.file = result.file.replace(/^\.\//, ''); + if (!files[result.file]) { + files[result.file] = []; + } + + if (globals) { + globals.forEach(function (global) { + files[result.file].push({ + severity: 'warning', + line: global.line, + column: 0, + message: "Implied global '" + global.name + "'", + source: 'jshint.implied-globals' + }); + }); + } + if (unuseds) { + unuseds.forEach(function (unused) { + files[result.file].push({ + severity: 'warning', + line: unused.line, + column: 0, + message: "Unused variable: '" + unused.name + "'", + source: 'jshint.implied-unuseds' + }); + }); + } + }); + + out.push(""); + out.push(""); + + for (fileName in files) { + if (files.hasOwnProperty(fileName)) { + out.push("\t"); + for (i = 0; i < files[fileName].length; i++) { + issue = files[fileName][i]; + out.push( + "\t\t" + ); + } + out.push("\t"); + } + } + + out.push(""); + + process.stdout.write(out.join("\n") + "\n"); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/default.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/default.js index 92f9902..90805d8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/default.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/default.js @@ -1,5 +1,5 @@ module.exports = { - reporter: function (results, data) { + reporter: function (results) { var len = results.length, str = '', file, error; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/non_error.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/non_error.js index d8c3243..6b1f8c4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/non_error.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/non_error.js @@ -1,7 +1,7 @@ /*jshint node: true */ module.exports = { - reporter: function (results, data, done) { + reporter: function (results, data) { var len = results.length, str = '', file, error, globals, unuseds; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/.npmignore deleted file mode 100644 index 496ee2c..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/.npmignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/Makefile deleted file mode 100644 index 5e9c4b0..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -test: - node test/test.js - -.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/index.js deleted file mode 100644 index dd1cb00..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/argsparser'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/lib/argsparser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/lib/argsparser.js deleted file mode 100644 index d3a8092..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/lib/argsparser.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Parser arguments array - * @param {Array} args optional arguments arrray. - * @return {Object} opts key value hash. - * @export - */ -exports.parse = function(args) { - // args is optional, default is process.argv - args = args || process.argv; - - var opts = {}, curSwitch; - - args.forEach(function(arg) { - // its a switch - if (/^(-|--)/.test(arg) || !curSwitch) { - opts[arg] = true; - curSwitch = arg; - // this arg is a data - } else { - if (arg === 'false') { - arg = false; - } else if (arg === 'true') { - arg = true; - } else if (!isNaN(arg)) { - arg = Number(arg); - } - - // it was a boolean switch per default, - // now it has got a val - if (typeof opts[curSwitch] === 'boolean') { - opts[curSwitch] = arg; - } else if (Array.isArray(opts[curSwitch])) { - opts[curSwitch].push(arg); - } else { - opts[curSwitch] = [opts[curSwitch], arg]; - } - } - }); - - return opts; -}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/package.json deleted file mode 100644 index f70b46f..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "argsparser", - "description": "A tiny command line arguments parser", - "version": "0.0.6", - "author": { - "name": "Oleg Slobodskoi", - "email": "oleg008@gmail.com" - }, - "repository": { - "type": "git", - "url": "http://github.com/kof/node-argsparser.git" - }, - "keywords": [ - "arguments", - "options", - "command line", - "parser" - ], - "engines": { - "node": ">= 0.2.0" - }, - "scripts": { - "test": "node ./test/test.js" - }, - "licenses": [ - { - "type": "MIT", - "url": "http://www.opensource.org/licenses/mit-license.php" - } - ], - "readme": "## Yet another tiny arguments parser for node\n\n## Features\n * extremely tiny\n * instead to parse all possible spellings, it uses just some simple rules\n\n## How this parser works\nThe target is to get a key-value object from an array. A key can be the first element or element prefixed by \"-\" and \"--\" (switch). \nSo the parser loops through the array and looks for keys. After he could detect an a key all next elements will be added as a value of this key until he find another key.\nIf there is no value, then the key is true (boolean). If there are a lot of values, then the key is an array.\n\n## Examples\n\nnode script.js -> {\"node\": \"script.js\"}\n\nnode script.js -o -> {\"node\": \"script.js\", \"-o\": true}\n\nnode script.js -o test -> {\"node\": \"script.js\", \"-o\": \"test\"}\n\nnode script.js -a testa --b testb -> {node: \"script.js\", \"-a\": \"testa\", \"--b\": \"testb\"}\n \nnode script.js -paths /test.js /test1.js -> {node: \"script.js\", \"-paths\": [\"/test.js\", \"/test1.js\"]}\n\n## Usage\n\n // per default it parses process.argv\n var args = require( \"argsparser\" ).parse(); // {\"node\": \"/path/to/your/script.js\"}\n \n // optional you can pass your own arguments array\n var args = require( \"argsparser\" ).parse([\"-a\", \"test\"]); // {\"-a\": \"test\"}\n\n \n## Installation\n npm install argsparser ", - "_id": "argsparser@0.0.6", - "_from": "argsparser@>=0.0.3" -} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/readme.md deleted file mode 100644 index 9cde9ae..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/readme.md +++ /dev/null @@ -1,34 +0,0 @@ -## Yet another tiny arguments parser for node - -## Features - * extremely tiny - * instead to parse all possible spellings, it uses just some simple rules - -## How this parser works -The target is to get a key-value object from an array. A key can be the first element or element prefixed by "-" and "--" (switch). -So the parser loops through the array and looks for keys. After he could detect an a key all next elements will be added as a value of this key until he find another key. -If there is no value, then the key is true (boolean). If there are a lot of values, then the key is an array. - -## Examples - -node script.js -> {"node": "script.js"} - -node script.js -o -> {"node": "script.js", "-o": true} - -node script.js -o test -> {"node": "script.js", "-o": "test"} - -node script.js -a testa --b testb -> {node: "script.js", "-a": "testa", "--b": "testb"} - -node script.js -paths /test.js /test1.js -> {node: "script.js", "-paths": ["/test.js", "/test1.js"]} - -## Usage - - // per default it parses process.argv - var args = require( "argsparser" ).parse(); // {"node": "/path/to/your/script.js"} - - // optional you can pass your own arguments array - var args = require( "argsparser" ).parse(["-a", "test"]); // {"-a": "test"} - - -## Installation - npm install argsparser \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/test/test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/test/test.js deleted file mode 100644 index 811de42..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/argsparser/test/test.js +++ /dev/null @@ -1,39 +0,0 @@ -var a = require('assert'), - util = require('util'), - parse = require('../lib/argsparser').parse; - -util.print('Run tests...\n'); - -a.deepEqual(parse(), {node: __filename}, 'node script.js'); - -a.deepEqual(parse(['-o']), {'-o': true}, 'node script.js -o'); - -a.deepEqual(parse(['-o', 'true']), {'-o': true}, 'node script.js -o true'); - -a.deepEqual(parse(['-o', 'false']), {'-o': false}, 'node script.js -o false'); - -a.deepEqual(parse(['-o', '123']), {'-o': 123}, 'node script.js -o 123'); - -a.deepEqual(parse(['--token', 'bla--bla']), {'--token': 'bla--bla'}, 'node script.js --token bla--bla'); - -a.deepEqual(parse(['-o', '123.456']), {'-o': 123.456}, 'node script.js -o 123.456'); - -a.deepEqual(parse(['-o', 'test']), {'-o': 'test'}, 'node script.js -o test'); - -a.deepEqual(parse(['-a', 'testa', '-b', 'testb']), {'-a': 'testa', '-b': 'testb'}, 'node script.js -a testa -b testb'); - -a.deepEqual(parse(['--a', 'testa', '--b', 'testb']), {'--a': 'testa', '--b': 'testb'}, 'node script.js --a testa --b testb '); - -a.deepEqual(parse(['-a', 'testa', '--b', 'testb']), {'-a': 'testa', '--b': 'testb'}, 'node script.js -a testa --b testb'); - -a.deepEqual(parse(['--a', 'testa', '-b', 'testb']), {'--a': 'testa', '-b': 'testb'}, 'node script.js --a testa -b testb'); - -a.deepEqual(parse(['-paths', '/test.js', '/test1.js']), {'-paths': ['/test.js', '/test1.js']}, 'node script.js -paths /test.js /test1.js'); - -a.deepEqual(parse(['--paths', '/test.js', '/test1.js']), {'--paths': ['/test.js', '/test1.js']}, 'node script.js --paths /test.js /test1.js'); - -a.deepEqual(parse(['--paths', '/test.js', '/test1.js', '-a', 'testa']), {'--paths': ['/test.js', '/test1.js'], '-a': 'testa'}, 'node script.js --paths /test.js /test1.js -a testa'); - -a.deepEqual(parse(['--port', '80', '8080']), {'--port': [80, 8080]}, 'node server.js --port 80 8080'); - -util.print('All tests ok\n'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/README.md new file mode 100644 index 0000000..0fe30d4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/README.md @@ -0,0 +1,196 @@ +**cli is a toolkit for rapidly building command line apps - it includes:** + +- Full featured opts/args parser +- Plugin support for adding common options and switches +- Helper methods for working with input/output and spawning child processes +- Output colored/styled messages, [progress bars](https://github.com/chriso/cli/blob/master/examples/progress.js) or [spinners](https://github.com/chriso/cli/blob/master/examples/spinner.js) +- Command [auto-completion](https://github.com/chriso/cli/blob/master/examples/command.js) and [glob support](https://github.com/chriso/cli/blob/master/examples/glob.js) + +Install using `npm install cli` or just bundle [cli.js](https://github.com/chriso/cli/raw/master/cli-min.js) with your app. + +## Example apps + +### sort.js + +```javascript +#!/usr/bin/env node +require('cli').withStdinLines(function(lines, newline) { + this.output(lines.sort().join(newline)); +}); +``` + +Try it out + +```bash +$ ./sort.js < input.txt +``` + +Let's add support for an `-n` switch to use a numeric sort, and a `-r` switch to reverse output - only 5 extra lines of code (!) + +```javascript +var cli = require('cli'), options = cli.parse(); + +cli.withStdinLines(function(lines, newline) { + lines.sort(!options.n ? null : function(a, b) { + return parseInt(a) > parseInt(b); + }); + if (options.r) lines.reverse(); + this.output(lines.join(newline)); +}); +``` + +### static.js + +Let's create a static file server with daemon support to see the opts parser + plugins in use - note: this requires `npm install creationix daemon` + +```javascript +var cli = require('cli').enable('daemon', 'status'); //Enable 2 plugins + +cli.parse({ + log: ['l', 'Enable logging'], + port: ['p', 'Listen on this port', 'number', 8080], + serve: [false, 'Serve static files from PATH', 'path', './public'] +}); + +cli.main(function(args, options) { + var server, middleware = []; + + if (options.log) { + this.debug('Enabling logging'); + middleware.push(require('creationix/log')()); + } + + this.debug('Serving files from ' + options.serve); + middleware.push(require('creationix/static')('/', options.serve, 'index.html')); + + server = this.createServer(middleware).listen(options.port); + + this.ok('Listening on port ' + options.port); +}); +``` + +To output usage information + +```bash +$ ./static.js --help +``` + +To create a daemon that serves files from */tmp*, run + +```bash +$ ./static.js -ld --serve=/tmp +``` + +For more examples, see [./examples](https://github.com/chriso/cli/tree/master/examples) + +## Helper methods + +cli has methods that collect stdin (newline is autodetected as \n or \r\n) + +```javascript +cli.withStdin(callback); //callback receives stdin as a string +cli.withStdinLines(callback); //callback receives stdin split into an array of lines (lines, newline) +``` + +cli also has a lower level method for working with input line by line (see [./examples/cat.js](https://github.com/chriso/cli/blob/master/examples/cat.js) for an example). + +```javascript +cli.withInput(file, function (line, newline, eof) { + if (!eof) { + this.output(line + newline); + } +}); +``` + +*Note: `file` can be omitted if you want to work with stdin* + +To output a progress bar, call + +```javascript +cli.progress(progress); //Where 0 <= progress <= 1 +``` + +To spawn a child process, use + +```javascript +cli.exec(cmd, callback); //callback receives the output of the process (split into lines) +``` + +cli also comes bundled with kof's [node-natives](https://github.com/kof/node-natives) (access with cli.native) and creationix' [stack](https://github.com/creationix/stack) (access with cli.createServer) + +## Plugins + +Plugins are a way of adding common opts and can be enabled using + +```javascript +cli.enable(plugin1, [plugin2, ...]); //To disable, use the equivalent disable() method +``` + +**help** - *enabled by default* + +Adds `-h,--help` to output auto-generated usage information + +**version** + +Adds `-v,--version` to output version information for the app. cli will attempt to locate and parse a nearby *package.json* + +To set your own app name and version, use `cli.setApp(app_name, version)` + +**status** + +Adds options to show/hide the stylized status messages that are output to the console when using one of these methods + +```javascript +cli.debug(msg); //Only shown when using --debug +cli.error(msg); +cli.fatal(msg); //Exits the process after outputting msg +cli.info(msg); +cli.ok(msg); +``` + +`-k,--no-color` will omit ANSI color escapes from the output + +**glob** - *requires* `npm install glob` + +Enables glob matching of arguments + +**daemon** - *requires* `npm install daemon` + +Adds `-d,--daemon ARG` for daemonizing the process and controlling the resulting daemon + +`ARG` can be either start (default), stop, restart, pid (outputs the daemon's pid if it's running), or log (output the daemon's stdout+stderr) + +**timeout** + +Adds `-t,--timeout N` to exit the process after N seconds with an error + +**catchall** + +Adds `-c,--catch` to catch and output uncaughtExceptions and resume execution + +*Note: Plugins are automatically disabled if an option or switch of the same name is already defined* + +## LICENSE + +(MIT license) + +Copyright (c) 2010 Chris O'Hara + +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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/cli.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/cli.js new file mode 100644 index 0000000..91fa4db --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/cli.js @@ -0,0 +1,1125 @@ +/** + * Copyright (c) 2010 Chris O'Hara + * + * 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. + */ + + //Note: cli includes kof/node-natives and creationix/stack. I couldn't find + //license information for either - contact me if you want your license added + +var cli = exports, + argv, curr_opt, curr_val, full_opt, is_long, + short_tags = [], opt_list, parsed = {}, + usage, argv_parsed, command_list, commands, + daemon, daemon_arg, no_color, show_debug; + +cli.app = null; +cli.version = null; +cli.argv = []; +cli.argc = 0; + +cli.options = {}; +cli.args = []; +cli.command; + +cli.width = 70; +cli.option_width = 25; + +/** + * Bind kof's node-natives (https://github.com/kof/node-natives) to `cli.native` + * + * Rather than requiring node natives (e.g. var fs = require('fs')), all + * native modules can be accessed like `cli.native.fs` + */ +cli.native = {}; +var define_native = function (module) { + Object.defineProperty(cli.native, module, { + enumerable: true, + configurable: true, + get: function() { + delete cli.native[module]; + return cli.native[module] = require(module); + } + }); +}; +var natives = process.binding('natives'); +for (var module in natives) { + define_native(module); +} + +cli.output = cli.native.util.print; +cli.exit = process.exit; + +/** + * Define plugins. Plugins can be enabled and disabled by calling: + * + * `cli.enable(plugin1, [plugin2, ...])` + * `cli.disable(plugin1, [plugin2, ...])` + * + * Methods are chainable - `cli.enable(plugin).disable(plugin2)`. + * + * The 'help' plugin is enabled by default. + */ +var enable = { + help: true, //Adds -h, --help + version: false, //Adds -v,--version => gets version by parsing a nearby package.json + daemon: false, //Adds -d,--daemon [ARG] => (see cli.daemon() below) + status: false, //Adds -k,--no-color & --debug => display plain status messages /display debug messages + timeout: false, //Adds -t,--timeout N => timeout the process after N seconds + catchall: false, //Adds -c,--catch => catch and output uncaughtExceptions + glob: false //Adds glob matching => use cli.glob(arg) +} +cli.enable = function (/*plugins*/) { + Array.prototype.slice.call(arguments).forEach(function (plugin) { + switch (plugin) { + case 'daemon': + try { + daemon = require('daemon'); + if (typeof daemon.daemonize !== 'function') { + throw 'Invalid module'; + } + } catch (e) { + cli.fatal('daemon.node not installed. Please run `npm install daemon`'); + } + break; + case 'catchall': + process.on('uncaughtException', function (err) { + cli.error('Uncaught exception: ' + (err.msg || err)); + }); + break; + case 'help': case 'version': case 'status': + case 'autocomplete': case 'timeout': + //Just add switches. + break; + case 'glob': + cli.glob = require('glob'); + break; + default: + cli.fatal('Unknown plugin "' + plugin + '"'); + break; + } + enable[plugin] = true; + }); + return cli; +} +cli.disable = function (/*plugins*/) { + Array.prototype.slice.call(arguments).forEach(function (plugin) { + if (enable[plugin]) { + enable[plugin] = false; + } + }); + return cli; +} + +/** + * Sets argv (default is process.argv). + * + * @param {Array|String} argv + * @param {Boolean} keep_arg0 (optional - default is false) + * @api public + */ +cli.setArgv = function (arr, keep_arg0) { + if (typeof arr == 'string') { + arr = arr.split(' '); + } else { + arr = arr.slice(); + } + cli.app = arr.shift(); + //Strip off argv[0] if it's a node binary + if (!keep_arg0 && ('node' === cli.native.path.basename(cli.app) + || process.execPath === cli.app)) { + cli.app = arr.shift(); + } + cli.app = cli.native.path.basename(cli.app); + argv_parsed = false; + cli.args = cli.argv = argv = arr; + cli.argc = argv.length; +}; +cli.setArgv(process.argv); + +/** + * Returns the next opt, or false if no opts are found. + * + * @return {String} opt + * @api public + */ +cli.next = function () { + if (!argv_parsed) { + cli.args = []; + argv_parsed = true; + } + + curr_val = null; + + //If we're currently in a group of short opts (e.g. -abc), return the next opt + if (short_tags.length) { + curr_opt = short_tags.shift(); + full_opt = '-' + curr_opt; + return curr_opt; + } + + if (!argv.length) { + return false; + } + + curr_opt = argv.shift(); + + //If an escape sequence is found (- or --), subsequent opts are ignored + if (curr_opt === '-' || curr_opt === '--') { + while (argv.length) { + cli.args.push(argv.shift()); + } + return false; + } + + //If the next element in argv isn't an opt, add it to the list of args + if (curr_opt[0] !== '-') { + cli.args.push(curr_opt); + return cli.next(); + } else { + //Check if the opt is short/long + is_long = curr_opt[1] === '-'; + curr_opt = curr_opt.substr(is_long ? 2 : 1); + } + + //Accept grouped short opts, e.g. -abc => -a -b -c + if (!is_long && curr_opt.length > 1) { + short_tags = curr_opt.split(''); + return cli.next(); + } + + var eq, len; + + //Check if the long opt is in the form --option=VALUE + if (is_long && (eq = curr_opt.indexOf('=')) >= 0) { + curr_val = curr_opt.substr(eq + 1); + curr_opt = curr_opt.substr(0, eq); + len = curr_val.length; + //Allow values to be quoted + if ((curr_val[0] === '"' && curr_val[len - 1] === '"') || + (curr_val[0] === "'" && curr_val[len - 1] === "'")) + { + curr_val = curr_val.substr(1, len-2); + } + if (curr_val.match(/^[0-9]+$/)) { + curr_val = parseInt(curr_val, 10); + } + } + + //Save the opt representation for later + full_opt = (is_long ? '--' : '-') + curr_opt; + + return curr_opt; +}; + +/** + * Parses command line opts. + * + * `opts` must be an object with opts defined like: + * long_tag: [short_tag, description, value_type, default_value]; + * + * `commands` is an optional array or object for apps that are of the form + * my_app [OPTIONS] [ARGS] + * The command list is output with usage information + there is bundled + * support for auto-completion, etc. + * + * See README.md for more information. + * + * @param {Object} opts + * @param {Object} commands (optional) + * @return {Object} opts (parsed) + * @api public + */ +cli.parse = function (opts, command_def) { + var default_val, i, parsed = cli.options, seen, + catch_all = !opts; + opt_list = opts || {}; + commands = command_def; + command_list = commands || []; + if (commands && !Array.isArray(commands)) { + command_list = Object.keys(commands); + } + while (o = cli.next()) { + seen = false; + for (opt in opt_list) { + if (!(opt_list[opt] instanceof Array)) { + continue; + } + if (!opt_list[opt][0]) { + opt_list[opt][0] = opt; + } + if (o === opt || o === opt_list[opt][0]) { + seen = true; + if (opt_list[opt].length === 2) { + parsed[opt] = true; + break; + } + default_val = null; + if (opt_list[opt].length === 4) { + default_val = opt_list[opt][3]; + } + if (opt_list[opt][2] instanceof Array) { + for (i = 0, l = opt_list[opt][2].length; i < l; i++) { + if (typeof opt_list[opt][2][i] === 'number') { + opt_list[opt][2][i] += ''; + } + } + parsed[opt] = cli.getArrayValue(opt_list[opt][2], is_long ? null : default_val); + break; + } + if (opt_list[opt][2].toLowerCase) { + opt_list[opt][2] = opt_list[opt][2].toLowerCase(); + } + switch (opt_list[opt][2]) { + case 'string': case 1: case true: + parsed[opt] = cli.getValue(default_val); + break; + case 'int': case 'number': case 'num': + case 'time': case 'seconds': case 'secs': case 'minutes': case 'mins': + case 'x': case 'n': + parsed[opt] = cli.getInt(default_val); + break; + case 'float': case 'decimal': + parsed[opt] = cli.getFloat(default_val); + break; + case 'path': case 'file': case 'directory': case 'dir': + parsed[opt] = cli.getPath(default_val, opt_list[opt][2]); + break; + case 'email': + parsed[opt] = cli.getEmail(default_val); + break; + case 'url': case 'uri': case 'domain': case 'host': + parsed[opt] = cli.getUrl(default_val, opt_list[opt][2]); + break; + case 'ip': + parsed[opt] = cli.getIp(default_val); + break; + case 'bool': case 'boolean': case 'on': + parsed[opt] = true; + break; + case 'false': case 'off': case false: case 0: + parsed[opt] = false; + break; + default: + cli.fatal('Unknown opt type "' + opt_list[opt][2] + '"'); + } + break; + } + } + if (process.env.NODE_DISABLE_COLORS) { + no_color = true; + } + if (!seen) { + if (enable.help && (o === 'h' || o === 'help')) { + cli.getUsage(); + process.exit(); + } else if (enable.version && (o === 'v' || o === 'version')) { + if (cli.version == null) { + cli.parsePackageJson(); + } + console.error(cli.app + ' v' + cli.version); + process.exit(); + } else if (enable.daemon && (o === 'd' || o === 'daemon')) { + daemon_arg = cli.getArrayValue(['start','stop','restart','pid','log'], is_long ? null : 'start'); + continue; + } else if (enable.catchall && (o === 'c' || o === 'catch')) { + continue; + } else if (enable.status && (o === 'k' || o === 'no-color' || o === 'debug')) { + no_color = (o === 'k' || o === 'no-color'); + show_debug = o === 'debug'; + continue; + } else if (enable.timeout && (o === 't' || o === 'timeout')) { + var secs = cli.getInt(); + setTimeout(function () { + cli.fatal('Process timed out after ' + secs + 's'); + }, secs * 1000); + continue; + } else if (catch_all) { + parsed[o] = curr_val || true; + continue; + } + cli.fatal('Unknown option ' + full_opt); + } + } + //Fill the remaining options with their default value or null + for (opt in opt_list) { + default_val = opt_list[opt].length === 4 ? opt_list[opt][3] : null; + if (!(opt_list[opt] instanceof Array)) { + parsed[opt] = opt_list[opt]; + continue; + } else if (typeof parsed[opt] === 'undefined') { + parsed[opt] = default_val; + } + } + if (command_list.length) { + if (cli.args.length === 0) { + if (enable.help) { + cli.getUsage(); + } else { + cli.fatal('A command is required (' + command_list.join(', ') + ').'); + } + process.exit(1); + } else { + cli.command = cli.autocompleteCommand(cli.args.shift()); + } + } + cli.argc = cli.args.length; + return parsed; +}; + +/** + * Helper method for matching a command from the command list. + * + * @param {String} command + * @return {String} full_command + * @api public + */ +cli.autocompleteCommand = function (command) { + var list; + if (!(command_list instanceof Array)) { + list = Object.keys(command_list); + } else { + list = command_list; + } + var i, j = 0, c = command.length, tmp_list; + if (list.length === 0 || list.indexOf(command) !== -1) { + return command; + } + for (i = 0; i < c; i++) { + tmp_list = []; + l = list.length; + if (l <= 1) break; + for (j = 0; j < l; j++) + if (list[j].length >= i && list[j][i] === command[i]) + tmp_list.push(list[j]); + list = tmp_list; + } + l = list.length; + if (l === 1) { + return list[0]; + } else if (l === 0) { + cli.fatal('Unknown command "' + command + '"' + (enable.help ? '. Please see --help for more information' : '')); + } else { + list.sort(); + cli.fatal('The command "' + command + '" is ambiguous and could mean "' + list.join('", "') + '"'); + } +}; + +/** + * Adds methods to output styled status messages to stderr. + * + * Added methods are cli.info(msg), cli.error(msg), cli.ok(msg), and + * cli.debug(msg). + * + * To control status messages, use the 'status' plugin + * 1) debug() messages are hidden by default. Display them with + * the --debug opt. + * 2) to hide all status messages, use the -s or --silent opt. + * + * @api private + */ +cli.status = function (msg, type) { + var pre; + switch (type) { + case 'info': + pre = no_color ? 'INFO:' : '\x1B[33mINFO\x1B[0m:'; + break; + case 'debug': + pre = no_color ? 'DEBUG:' : '\x1B[36mDEBUG\x1B[0m:'; + break; + case 'error': + case 'fatal': + pre = no_color ? 'ERROR:' : '\x1B[31mERROR\x1B[0m:'; + break; + case 'ok': + pre = no_color ? 'OK:' : '\x1B[32mOK\x1B[0m:'; + break; + } + msg = pre + ' ' + msg; + if (type === 'fatal') { + console.error(msg); + process.exit(1); + } + if (enable.status && !show_debug && type === 'debug') { + return; + } + console.error(msg); +}; +['info','error','ok','debug','fatal'].forEach(function (type) { + cli[type] = function (msg) { + cli.status(msg, type); + }; +}); + +/** + * Sets the app name and version. + * + * Usage: + * setApp('myapp', '0.1.0'); + * setApp('./package.json'); //Pull name/version from package.json + * + * @param {String} name + * @return cli (for chaining) + * @api public + */ +cli.setApp = function (name, version) { + if (name.indexOf('package.json') !== -1) { + cli.parsePackageJson(name); + } else { + cli.app = name; + cli.version = version; + } + return cli; +}; + +/** + * Parses the version number from package.json. If no path is specified, cli + * will attempt to locate a package.json in ./, ../ or ../../ + * + * @param {String} path (optional) + * @api public + */ +cli.parsePackageJson = function (path) { + var parse_packagejson = function (path) { + var packagejson = JSON.parse(cli.native.fs.readFileSync(path, 'utf8')); + cli.version = packagejson.version; + cli.app = packagejson.name; + }; + var try_all = function (arr, func, err) { + for (var i = 0, l = arr.length; i < l; i++) { + try { + func(arr[i]); + return; + } catch (e) { + if (i === l-1) { + cli.fatal(err); + } + } + } + }; + try { + if (path) { + return parse_packagejson(path); + } + try_all([ + __dirname + '/package.json', + __dirname + '/../package.json', + __dirname + '/../../package.json' + ], parse_packagejson); + } catch (e) { + cli.fatal('Could not detect ' + cli.app + ' version'); + } +}; + +/** + * Sets the usage string - default is `app [OPTIONS] [ARGS]`. + * + * @param {String} u + * @return cli (for chaining) + * @api public + */ +cli.setUsage = function (u) { + usage = u; + return cli; +}; + +var pad = function (str, len) { + if (typeof len === 'undefined') { + len = str; + str = ''; + } + if (str.length < len) { + len -= str.length; + while (len--) str += ' '; + } + return str; +}; + +/** + * Automatically build usage information from the opts list. If the help + * plugin is enabled (default), this info is displayed with -h, --help. + * + * @api public + */ +cli.getUsage = function () { + var short, desc, optional, line, seen_opts = [], + switch_pad = cli.option_width; + + var trunc_desc = function (pref, desc, len) { + var pref_len = pref.length, + desc_len = cli.width - pref_len, + truncated = ''; + if (desc.length <= desc_len) { + return desc; + } + var desc_words = (desc+'').split(' '), chars = 0, word; + while (desc_words.length) { + truncated += (word = desc_words.shift()) + ' '; + chars += word.length; + if (desc_words.length && chars + desc_words[0].length > desc_len) { + truncated += '\n' + pad(pref_len); + chars = 0; + } + } + return truncated; + }; + + usage = usage || cli.app + ' [OPTIONS]' + (command_list.length ? ' ' : '') + ' [ARGS]'; + if (no_color) { + console.error('Usage:\n ' + usage); + console.error('Options: '); + } else { + console.error('\x1b[1mUsage\x1b[0m:\n ' + usage); + console.error('\n\x1b[1mOptions\x1b[0m: '); + } + for (opt in opt_list) { + + if (opt.length === 1) { + long = opt_list[opt][0]; + short = opt; + } else { + long = opt; + short = opt_list[opt][0]; + } + + //Parse opt_list + desc = opt_list[opt][1].trim(); + type = opt_list[opt].length >= 3 ? opt_list[opt][2] : null; + optional = opt_list[opt].length === 4 ? opt_list[opt][3] : null; + + //Build usage line + if (short === long) { + if (short.length === 1) { + line = ' -' + short; + } else { + line = ' --' + long; + } + } else { + line = ' -' + short + ', --' + long; + } + line += ' '; + + if (type) { + if (type instanceof Array) { + desc += '. VALUE must be either [' + type.join('|') + ']'; + type = 'VALUE'; + } + if (type === true || type === 1) { + type = long.toUpperCase(); + } + type = type.toUpperCase(); + if (type === 'FLOAT' || type === 'INT') { + type = 'NUMBER'; + } + line += optional ? '[' + type + ']' : type; + } + line = pad(line, switch_pad); + line += trunc_desc(line, desc); + line += optional ? ' (Default is ' + optional + ')' : ''; + console.error(line.replace('%s', '%\0s')); + + seen_opts.push(short); + seen_opts.push(long); + } + if (enable.timeout && seen_opts.indexOf('t') === -1 && seen_opts.indexOf('timeout') === -1) { + console.error(pad(' -t, --timeout N', switch_pad) + 'Exit if the process takes longer than N seconds'); + } + if (enable.status) { + if (seen_opts.indexOf('k') === -1 && seen_opts.indexOf('no-color') === -1) { + console.error(pad(' -k, --no-color', switch_pad) + 'Omit color from output'); + } + if (seen_opts.indexOf('debug') === -1) { + console.error(pad(' --debug', switch_pad) + 'Show debug information'); + } + } + if (enable.catchall && seen_opts.indexOf('c') === -1 && seen_opts.indexOf('catch') === -1) { + console.error(pad(' -c, --catch', switch_pad) + 'Catch unanticipated errors'); + } + if (enable.daemon && seen_opts.indexOf('d') === -1 && seen_opts.indexOf('daemon') === -1) { + console.error(pad(' -d, --daemon [ARG]', switch_pad) + 'Daemonize the process. Control the daemon using [start, stop, restart, log, pid]'); + } + if (enable.version && seen_opts.indexOf('v') === -1 && seen_opts.indexOf('version') === -1) { + console.error(pad(' -v, --version', switch_pad) + 'Display the current version'); + } + if (enable.help && seen_opts.indexOf('h') === -1 && seen_opts.indexOf('help') === -1) { + console.error(pad(' -h, --help', switch_pad) + 'Display help and usage details'); + } + if (command_list.length) { + console.error('\n\x1b[1mCommands\x1b[0m: '); + if (!Array.isArray(commands)) { + for (var c in commands) { + line = ' ' + pad(c, switch_pad - 2); + line += trunc_desc(line, commands[c]); + console.error(line); + } + } else { + command_list.sort(); + console.error(' ' + trunc_desc(' ', command_list.join(', '))); + } + } + process.exit(); +}; + +/** + * Generates an error message when an opt is incorrectly used. + * + * @param {String} expects (e.g. 'a value') + * @param {String} type (e.g. 'VALUE') + * @api public + */ +cli.getOptError = function (expects, type) { + var err = full_opt + ' expects ' + expects + + '. Use `' + cli.app + ' ' + full_opt + (is_long ? '=' : ' ') + type + '`'; + return err; +}; + +/** + * Gets the next opt value and validates it with an optional validation + * function. If validation fails or no value can be obtained, this method + * will return the default value (if specified) or exit with err_msg. + * + * @param {String} default_val + * @param {Function} validate_func + * @param {String} err_msg + * @api public + */ +cli.getValue = function (default_val, validate_func, err_msg) { + err_msg = err_msg || cli.getOptError('a value', 'VALUE'); + + var value; + + try { + if (curr_val) { + if (validate_func) { + curr_val = validate_func(curr_val); + } + return curr_val; + } + + //Grouped short opts aren't allowed to have values + if (short_tags.length) { + throw 'Short tags'; + } + + //If there's no args left or the next arg is an opt, return the + //default value (if specified) - otherwise fail + if (!argv.length || argv[0][0] === '-') { + throw 'No value'; + } + + value = argv.shift(); + + if (value.match(/^[0-9]+$/)) { + value = parseInt(value, 10); + } + + //Run the value through a validation/transformation function if specified + if (validate_func) { + value = validate_func(value); + } + } catch (e) { + + //The value didn't pass the validation/transformation. Unshift the value and + //return the default value (if specified) + if (value) { + argv.unshift(value); + } + return default_val != null ? default_val : cli.fatal(err_msg); + } + return value; +}; + +cli.getInt = function (default_val) { + return cli.getValue(default_val, function (value) { + if (typeof value === 'number') return value; + if (!value.match(/^(?:-?(?:0|[1-9][0-9]*))$/)) { + throw 'Invalid int'; + } + return parseInt(value); + }, cli.getOptError('a number', 'NUMBER')); +} + +cli.getFloat = function (default_val) { + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:-?(?:0|[1-9][0-9]*))?(?:\.[0-9]*)?$/)) { + throw 'Invalid float'; + } + return parseFloat(value, 10); + }, cli.getOptError('a number', 'NUMBER')); +} + +cli.getUrl = function (default_val, identifier) { + identifier = identifier || 'url'; + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/i)) { + throw 'Invalid URL'; + } + return value; + }, cli.getOptError('a ' + identifier, identifier.toUpperCase())); +} + +cli.getEmail = function (default_val) { + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/)) { + throw 'Invalid email'; + } + return value; + }, cli.getOptError('an email', 'EMAIL')); +} + +cli.getIp = function (default_val) { + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/)) { + throw 'Invalid IP'; + } + return value; + }, cli.getOptError('an IP', 'IP')); +} + +cli.getPath = function (default_val, identifier) { + identifier = identifier || 'path'; + return cli.getValue(default_val, function (value) { + if (value.match(/[?*:;{}]/)) { + throw 'Invalid path'; + } + return value; + }, cli.getOptError('a ' + identifier, identifier.toUpperCase())); +} + +cli.getArrayValue = function (arr, default_val) { + return cli.getValue(default_val, function (value) { + if (arr.indexOf(value) === -1) { + throw 'Unexpected value'; + } + return value; + }, cli.getOptError('either [' + arr.join('|') + ']', 'VALUE')); +} + +/** + * Gets all data from STDIN (with optional encoding) and sends it to callback. + * + * @param {String} encoding (optional - default is 'utf8') + * @param {Function} callback + * @api public + */ +cli.withStdin = function (encoding, callback) { + if (typeof encoding === 'function') { + callback = encoding; + encoding = 'utf8'; + } + var stream = process.openStdin(), data = ''; + stream.setEncoding(encoding); + stream.on('data', function (chunk) { + data += chunk; + }); + stream.on('end', function () { + callback.apply(cli, [data]); + }); +}; + +/** + * Gets all data from STDIN, splits the data into lines and sends it + * to callback (callback isn't called until all of STDIN is read. To + * process each line as it's received, see the method below + * + * @param {Function} callback + * @api public + */ +cli.withStdinLines = function (callback) { + cli.withStdin(function (data) { + var sep = data.indexOf('\r\n') !== -1 ? '\r\n' : '\n'; + callback.apply(cli, [data.split(sep), sep]); + }); +}; + +/** + * Asynchronously reads a file line by line. When a line is received, + * callback is called with (line, sep) - when EOF is reached, callback + * receives (null, null, true) + * + * @param {String} file (optional - default is 'stdin') + * @param {String} encoding (optional - default is 'utf8') + * @param {Function} callback (line, sep, eof) + * @api public + */ +cli.withInput = function (file, encoding, callback) { + if (typeof encoding === 'function') { + callback = encoding; + encoding = 'utf8'; + } else if (typeof file === 'function') { + callback = file; + encoding = 'utf8'; + file = 'stdin'; + } + if (file === 'stdin') { + file = process.openStdin(); + } else { + try { + file = cli.native.fs.createReadStream(file); + file.on('error', cli.fatal); + } catch (e) { + return cli.fatal(e); + } + } + file.setEncoding(encoding); + var lines = [], data = '', eof, sep; + file.on('data', function (chunk) { + if (eof) return; + data += chunk; + if (!sep) { + if (data.indexOf('\r\n') !== -1) { + sep = '\r\n'; + } else if (data.indexOf('\n') !== -1) { + sep = '\n'; + } else { + last_line = data; + return; + } + } + lines = data.split(sep); + data = eof ? null : lines.pop(); + while (lines.length) { + callback.apply(cli, [lines.shift(), sep, false]); + } + }); + file.on('end', function () { + eof = true; + if (data.length) { + callback.apply(cli, [data, sep || '', false]); + } + callback.apply(cli, [null, null, true]); + }); +}; + +/** + * A method for creating and controlling a daemon. + * + * `arg` can be: + * start = daemonizes the process + * stop = stops the daemon if it is running + * restart = alias for stop -> start + * pid = outputs the daemon's PID if it is running + * log = outputs the daemon's log file (stdout + stderr) + * + * @param {String} arg (Optional - default is 'start') + * @param {Function} callback + * @api public + */ +cli.daemon = function (arg, callback) { + if (typeof daemon === 'undefined') { + cli.fatal('Daemon is not initialized'); + } + + if (typeof arg === 'function') { + callback = arg; + arg = 'start'; + } + + var lock_file = '/tmp/' + cli.app + '.pid', + log_file = '/tmp/' + cli.app + '.log'; + + var start = function () { + daemon.daemonize(log_file, lock_file, function (err) { + if (err) return cli.error('Error starting daemon: ' + err); + callback(); + }); + }; + + var stop = function () { + try { + cli.native.fs.readFileSync(lock_file); + } catch (e) { + return cli.error('Daemon is not running'); + }; + daemon.kill(lock_file, function (err, pid) { + if (err && err.errno === 3) { + return cli.error('Daemon is not running'); + } else if (err) { + return cli.error('Error stopping daemon: ' + err.errno); + } + cli.ok('Successfully stopped daemon with pid: ' + pid); + }); + }; + + switch(arg) { + case 'stop': + stop(); + break; + case 'restart': + daemon.stop(lock_file, function () { + start(); + }); + break; + case 'log': + try { + cli.native.fs.createReadStream(log_file, {encoding: 'utf8'}).pipe(process.stdout); + } catch (e) { + return cli.error('No daemon log file'); + }; + break; + case 'pid': + try { + var pid = cli.native.fs.readFileSync(lock_file, 'utf8'); + cli.native.fs.statSync('/proc/' + pid); + cli.info(pid); + } catch (e) { + return cli.error('Daemon is not running'); + }; + break; + default: + start(); + break; + } +} + +/** + * The main entry method. Calling cli.main() is only necessary in + * scripts that have daemon support enabled. `callback` receives (args, options) + * + * @param {Function} callback + * @api public + */ +cli.main = function (callback) { + var after = function () { + callback.apply(cli, [cli.args, cli.options]); + }; + if (enable.daemon && daemon_arg) { + cli.daemon(daemon_arg, after); + } else { + after(); + } +} + +/** + * Bind creationix's stack (https://github.com/creationix/stack). + * + * Create a simple middleware stack by calling: + * + * cli.createServer(middleware).listen(port); + * + * @return {Server} server + * @api public + */ +cli.createServer = function(/*layers*/) { + var defaultStackErrorHandler = function (req, res, err) { + if (err) { + console.error(err.stack); + res.writeHead(500, {"Content-Type": "text/plain"}); + return res.end(err.stack + "\n"); + } + res.writeHead(404, {"Content-Type": "text/plain"}); + res.end("Not Found\n"); + }; + var handle = error = defaultStackErrorHandler, + layers = Array.prototype.slice.call(arguments); + + //Allow createServer(a,b,c) and createServer([a,b,c]) + if (layers.length && layers[0] instanceof Array) { + layers = layers[0]; + } + layers.reverse().forEach(function (layer) { + var child = handle; + handle = function (req, res) { + try { + layer(req, res, function (err) { + if (err) return error(req, res, err); + child(req, res); + }); + } catch (err) { + error(req, res, err); + } + }; + }); + return cli.native.http.createServer(handle); +}; + +/** + * A wrapper for child_process.exec(). + * + * If the child_process exits successfully, `callback` receives an array of + * stdout lines. The current process exits if the child process has an error + * and `errback` isn't defined. + * + * @param {String} cmd + * @param {Function} callback (optional) + * @param {Function} errback (optional) + * @api public + */ +cli.exec = function (cmd, callback, errback) { + cli.native.child_process.exec(cmd, function (err, stdout, stderr) { + err = err || stderr; + if (err) { + if (errback) { + return errback(err); + } + return cli.fatal('exec() failed\n' + err); + } + if (callback) { + callback(stdout.split('\n')); + } + }); +}; + +/** + * Helper method for outputting a progress bar to the console. + * + * @param {Number} progress (0 <= progress <= 1) + * @api public + */ +var last_progress_call, progress_len = 74; +cli.progress = function (progress) { + if (progress < 0 || progress > 1 || isNaN(progress)) return; + var now = (new Date()).getTime(); + if (last_progress_call && (now - last_progress_call) < 100 && progress !== 1) { + return; //Throttle progress calls + } + last_progress_call = now; + + + var barLength = Math.floor(progress_len * progress), + str = ''; + if (barLength == 0 && progress > 0) { + barLength = 1; + } + for (var i = 1; i <= progress_len; i++) { + str += i <= barLength ? '#' : ' '; + } + cli.native.util.print('[' + str + '] ' + Math.floor(progress * 100) + '%' + (progress === 1 ? '\n' : '\u000D')); +}; + +/** + * Helper method for outputting a spinner to the console. + * + * @param {String|Boolean} prefix (optional) + * @api public + */ +var spinnerInterval; +cli.spinner = function (prefix, end) { + if (end) { + cli.native.util.print('\u000D' + prefix); + return clearInterval(spinnerInterval); + } + prefix = prefix + ' ' || ''; + var spinner = ['-','\\','|','/'], i = 0, l = spinner.length; + spinnerInterval = setInterval(function () { + cli.native.util.print('\u000D' + prefix + spinner[i++]); + if (i == l) i = 0; + }, 200); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/cat.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/cat.js new file mode 100755 index 0000000..14c4e79 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/cat.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +var output_file = function (file) { + cli.withInput(file, function (line, sep, eof) { + if (!eof) { + cli.output(line + sep); + } else if (cli.args.length) { + output_file(cli.args.shift()); + } + }); +}; + +if (cli.args.length) { + output_file(cli.args.shift()); +} \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/command.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/command.js new file mode 100755 index 0000000..2f04491 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/command.js @@ -0,0 +1,16 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +//The second (optional) argument of cli.parse() is a command list +//Type `./command.js --help` for usage info + +//cli enables auto-completion of commands (similiar to npm), e.g. all of +//the following are equivalent and result in "Command is: install": +// $ ./command.js install +// $ ./command.js inst +// $ ./command.js i + +cli.parse(null, ['install', 'test', 'edit', 'remove', 'uninstall', 'ls']); + +console.log('Command is: ' + cli.command); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/echo.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/echo.js new file mode 100755 index 0000000..dac9cca --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/echo.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +/* All of the following commands are equivalent and write `foo\tbar foo` to out.txt + $ ./echo.js -n -e --output=out.txt "foo\tbar" "foo" + $ ./echo.js --newline --escape --output "out.txt" "foo\tbar" "foo" + $ ./echo.js -ne --output=out.txt "foo\tbar" "foo" + $ ./echo.js -en --output="out.txt" "foo\tbar" "foo" +*/ + +var cli = require('cli'); + +cli.parse({ + newline: ['n', 'Do not output the trailing newline'], + escape: ['e', 'Enable interpretation of backslash escapes'], + separator: ['s', 'Separate arguments using this value', 'string', ' '], + output: [false, 'Write to FILE rather than the console', 'file'] +}); + +cli.main(function (args, options) { + var output = '', i, j, l, output_stream; + + if (this.argc) { + if (options.escape) { + var replace = {'\\n':'\n','\\r':'\r','\\t':'\t','\\e':'\e','\\v':'\v','\\f':'\f','\\c':'\c','\\b':'\b','\\a':'\a','\\\\':'\\'}; + var escape = function (str) { + string += ''; + for (j in replace) { + string = string.replace(i, replace[i]); + } + return string; + } + for (i = 0, l = this.argc; i < l; i++) { + args[i] = escape(args[i]); + } + options.separator = escape(options.separator); + } + output += args.join(options.separator); + } + + if (!options.newline) { + output += '\n'; + } + + try { + if (options.output) { + output_stream = this.native.fs.createWriteStream(options.output) + } else { + output_stream = process.stdout; + } + output_stream.write(output); + } catch (e) { + this.fatal('Could not write to output stream'); + } +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/glob.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/glob.js new file mode 100755 index 0000000..12585c0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/glob.js @@ -0,0 +1,6 @@ +#!/usr/bin/env node + +var cli = require('cli').enable('glob'); + +//Running `./glob.js *.js` will output a list of .js files in this directory +console.log(cli.args); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/long_desc.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/long_desc.js new file mode 100755 index 0000000..63632f4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/long_desc.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node + +var cli = require('../'); + +//You can (optionally) boost the width of output with: +//cli.width = 120; + +//You can also adjust the width of the options/command definitions +//cli.option_width = 25; + +var long_desc = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s ' + + 'standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make' + + ' a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, ' + + 'remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing ' + + 'Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions' + + ' of Lorem Ipsum.'; + +cli.parse({ + foo: ['f', long_desc] +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/progress.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/progress.js new file mode 100755 index 0000000..300c674 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/progress.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +var i = 0, interval = setInterval(function () { + cli.progress(++i / 100); + if (i === 100) { + clearInterval(interval); + cli.ok('Finished!'); + } +}, 50); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/sort.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/sort.js new file mode 100755 index 0000000..5d22313 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/sort.js @@ -0,0 +1,18 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +var options = cli.parse({ + numeric: ['n', 'Compare using a numeric sort'], + reverse: ['r', 'Reverse the results'] +}); + +cli.withStdinLines(function (lines, newline) { + lines.sort(!options.numeric ? null : function (a, b) { + return parseInt(a) > parseInt(b); + }); + if (options.reverse) { + lines.reverse(); + } + this.output(lines.join(newline)); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/spinner.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/spinner.js new file mode 100755 index 0000000..6100001 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/spinner.js @@ -0,0 +1,9 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +cli.spinner('Working..'); + +setTimeout(function () { + cli.spinner('Working.. done!', true); //End the spinner +}, 3000); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/static.coffee b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/static.coffee new file mode 100755 index 0000000..cbf3b16 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/static.coffee @@ -0,0 +1,27 @@ +#!/usr/bin/env coffee + +cli = require 'cli' + +cli.enable('daemon','status') + .setUsage('static.coffee [OPTIONS]') + +cli.parse { + log: ['l', 'Enable logging'] + port: ['p', 'Listen on this port', 'number', 8080] + serve: [false, 'Serve static files from PATH', 'path', './public'] +} + +middleware = [] + +cli.main (args, options) -> + + if options.log + @debug 'Enabling logging' + middleware.push require('creationix/log')() + + @debug 'Serving files from ' + options.serve + middleware.push require('creationix/static')('/', options.serve, 'index.html') + + server = @createServer(middleware).listen options.port + + @ok 'Listening on port ' + options.port \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/static.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/static.js new file mode 100755 index 0000000..eb6fd24 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/examples/static.js @@ -0,0 +1,25 @@ +#!/usr/bin/env node + +var cli = require('cli').enable('status', 'daemon'); + +cli.parse({ + log: ['l', 'Enable logging'], + port: ['p', 'Listen on this port', 'number', 8080], + serve: [false, 'Serve static files from PATH', 'path', './public'] +}); + +cli.main(function (args, options) { + var server, middleware = []; + + if (options.log) { + this.debug('Enabling logging'); + middleware.push(require('creationix/log')()); + } + + this.debug('Serving files from ' + options.serve); + middleware.push(require('creationix/static')('/', options.serve, 'index.html')); + + server = this.createServer(middleware).listen(options.port); + + this.ok('Listening on port ' + options.port); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/index.js new file mode 100644 index 0000000..3966bd7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/index.js @@ -0,0 +1 @@ +module.exports = require('./cli'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/.npmignore new file mode 100644 index 0000000..2af4b71 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/.npmignore @@ -0,0 +1,2 @@ +.*.swp +test/a/ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/.travis.yml new file mode 100644 index 0000000..baa0031 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE new file mode 100644 index 0000000..0c44ae7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/README.md new file mode 100644 index 0000000..6e27df6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/README.md @@ -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} filenames found matching the pattern + +Perform an asynchronous glob search. + +## glob.sync(pattern, [options] + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* return: {Array} 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} 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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js new file mode 100644 index 0000000..be122df --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js @@ -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") diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js new file mode 100644 index 0000000..327a425 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js @@ -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") diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js new file mode 100644 index 0000000..10c87bc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js @@ -0,0 +1,604 @@ +// 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+1] +// 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) { + // console.error("cb with matches", 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) + + 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.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 + 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 {: 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._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] + if (this.debug) console.error("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) + } + + if (this.debug) console.error("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 + } + if (this.debug) { + console.error('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.charAt(0) === "/" && !this.nomount) { + prefix = path.join(this.root, prefix) + } + 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)) { + read = prefix = path.resolve("/", prefix) + if (this.debug) console.error('absolute: ', prefix, this.root, pattern) + } else read = prefix + + if (this.debug) console.error('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) + } + + 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) + } + if (this.debug) console.error('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 (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) + } + + if (this.debug) console.error('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 + if (this.debug) console.error(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}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/ + , 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 === "" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/.npmignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/.npmignore @@ -0,0 +1 @@ +node_modules/ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/README.md new file mode 100644 index 0000000..7d2e681 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/README.md @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/graceful-fs.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/graceful-fs.js new file mode 100644 index 0000000..be9951e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/graceful-fs.js @@ -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 + } + } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/package.json new file mode 100644 index 0000000..9ac2815 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/package.json @@ -0,0 +1,36 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "graceful-fs", + "description": "fs monkey-patching to avoid EMFILE and other problems", + "version": "1.1.14", + "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", + "EMFILE", + "error", + "handling", + "monkeypatch" + ], + "license": "BSD", + "readme": "Just like node's `fs` module, but it does an incremental back-off when\nEMFILE is encountered.\n\nUseful in asynchronous situations where one needs to try to open lots\nand lots of files.\n", + "readmeFilename": "README.md", + "_id": "graceful-fs@1.1.14", + "_from": "graceful-fs@~1.1.2" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/test/open.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/test/open.js new file mode 100644 index 0000000..d05f880 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/graceful-fs/test/open.js @@ -0,0 +1,41 @@ +var test = require('tap').test +var fs = require('../graceful-fs.js') + +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() + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md new file mode 100644 index 0000000..b2beaed --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js new file mode 100644 index 0000000..061b396 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js @@ -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 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json new file mode 100644 index 0000000..ada6137 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json @@ -0,0 +1,26 @@ +{ + "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", + "_id": "inherits@1.0.0", + "_from": "inherits@1" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/README.md new file mode 100644 index 0000000..6fd07d2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/README.md @@ -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! +``` + +## Features + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` + +### 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. **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 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. + + +## 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.) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/minimatch.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/minimatch.js new file mode 100644 index 0000000..5841be1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/minimatch.js @@ -0,0 +1,1079 @@ +;(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.monkeyPatch = monkeyPatch +function monkeyPatch () { + var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") + var orig = desc.value + desc.value = function (p) { + if (p instanceof Minimatch) return p.match(this) + return orig.call(this, p) + } + Object.defineProperty(String.prototype, desc) +} + +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.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) console.error(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) + }) + + if (options.debug) console.error(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + if (options.debug) console.error(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + if (options.debug) console.error(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) !== "{") { + // console.error(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error(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) { + // console.error("no sets") + return [pattern] + } + + var tail = braceExpand(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) { + // console.error("numset", numset[1], numset[2]) + var suf = braceExpand(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 = "" + } + + // console.error("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error("", 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) { + // console.error("didn't close", pattern) + return braceExpand("\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + // console.error("set", set) + // console.error("suffix", pattern.substr(i)) + var suf = braceExpand(pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + // console.error("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand(p, options) + }) + // console.error("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 = false + , 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}(?:$|\\\/))" + : "(?!\\.)" + + 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 + } + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + if (options.debug) { + console.error("%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 "!": + if (options.debug) { + console.error("%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) { + 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. + 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 === "!" ? "(?:(?!" : "(?:" + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + 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 + } + + 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 + "|" + }) + + // console.error("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) { + // console.error("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) + if (options.debug) { + console.error(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 + // console.error(this.pattern, "set", set) + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i] + var hit = this.matchOne(f, 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 + + if (options.debug) { + console.error("matchOne", + { "this": this + , file: file + , pattern: pattern }) + } + + if (options.matchBase && pattern.length === 1) { + file = path.basename(file.join("/")).split("/") + } + + if (options.debug) { + console.error("matchOne", file.length, pattern.length) + } + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + if (options.debug) { + console.error("matchOne loop") + } + var p = pattern[pi] + , f = file[fi] + + if (options.debug) { + console.error(pattern, p, f) + } + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + if (options.debug) + console.error('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) { + if (options.debug) + console.error('** 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] + + if (options.debug) { + console.error('\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)) { + if (options.debug) + console.error('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) === ".")) { + if (options.debug) + console.error("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + if (options.debug) + console.error('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 + // console.error("\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 + } + if (options.debug) { + console.error("string match", p, f, hit) + } + } else { + hit = f.match(p) + if (options.debug) { + console.error("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" + ) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/.npmignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/AUTHORS b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/AUTHORS similarity index 100% rename from node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/AUTHORS rename to node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/AUTHORS diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/README.md new file mode 100644 index 0000000..8ea0dd9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,46 @@ +# 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 number of items. 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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 0000000..4bec3e2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,191 @@ +;(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) + } + + var max + if (typeof options === 'number') { + max = options + options = { max: max } + } + max = options.max + + if (!options) options = {} + + var lengthCalculator = options.length || naiveLength + + if (typeof lengthCalculator !== "function") { + lengthCalculator = naiveLength + } + if (!max || !(typeof max === "number") || max <= 0 ) { + // a little bit silly. maybe this should throw? + max = Infinity + } + + var maxAge = options.maxAge || null + + var dispose = options.dispose + + var cache = Object.create(null) // hash of items by key + , lruList = Object.create(null) // list of items in order of use recency + , mru = 0 // most recently used + , length = 0 // number of items in the list + , itemCount = 0 + + + // resize the cache when the max changes. + Object.defineProperty(this, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + max = mL + // if it gets above double max, trim right away. + // otherwise, do it whenever it's convenient. + if (length > max) trim() + } + , get : function () { return max } + , enumerable : true + }) + + // resize the cache when the lengthCalculator changes. + Object.defineProperty(this, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + lengthCalculator = naiveLength + length = itemCount + for (var key in cache) { + cache[key].length = 1 + } + } else { + lengthCalculator = lC + length = 0 + for (var key in cache) { + cache[key].length = lengthCalculator(cache[key].value) + length += cache[key].length + } + } + + if (length > max) trim() + } + , get : function () { return lengthCalculator } + , enumerable : true + }) + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + + Object.defineProperty(this, "itemCount", + { get : function () { return itemCount } + , enumerable : true + }) + + this.reset = function () { + if (dispose) { + for (var k in cache) { + dispose(k, cache[k].value) + } + } + cache = {} + lruList = {} + mru = 0 + length = 0 + itemCount = 0 + } + + // Provided for debugging/dev purposes only. No promises whatsoever that + // this API stays stable. + this.dump = function () { + return cache + } + + this.set = function (key, value) { + if (hOP(cache, key)) { + // dispose of the old one before overwriting + if (dispose) dispose(key, cache[key].value) + if (maxAge) cache[key].now = Date.now() + cache[key].value = value + this.get(key) + return true + } + + var len = lengthCalculator(value) + var age = maxAge ? Date.now() : 0 + var hit = new Entry(key, value, mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > max) { + if (dispose) dispose(key, value) + return false + } + + length += hit.length + lruList[hit.lu] = cache[key] = hit + itemCount ++ + + if (length > max) trim() + return true + } + + this.get = function (key) { + if (!hOP(cache, key)) return + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + this.del(key) + return + } + delete lruList[hit.lu] + hit.lu = mru ++ + lruList[hit.lu] = hit + return hit.value + } + + this.del = function (key) { + if (!hOP(cache, key)) return + var hit = cache[key] + if (dispose) dispose(key, hit.value) + delete cache[key] + delete lruList[hit.lu] + length -= hit.length + itemCount -- + } + + function trim () { + if (length <= max) return + for (var k in lruList) { + if (length <= max) break; + var hit = lruList[k] + if (dispose) dispose(hit.key, hit.value) + length -= hit.length + delete cache[ hit.key ] + delete lruList[k] + } + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, mru, len, age) { + this.key = key + this.value = value + this.lu = mru + this.length = len + this.now = age +} + +})() diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/package.json new file mode 100644 index 0000000..e460f95 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,58 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.0.4", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + { + "name": "Carlos Brito Lage", + "email": "carlos@carloslage.net" + }, + { + "name": "Marko Mikulicic", + "email": "marko.mikulicic@isti.cnr.it" + }, + { + "name": "Trent Mick", + "email": "trentm@gmail.com" + }, + { + "name": "Kevin O'Hara", + "email": "kevinohara80@gmail.com" + }, + { + "name": "Marco Rogers", + "email": "marco.rogers@gmail.com" + }, + { + "name": "Jesse Dailey", + "email": "jesse.dailey@gmail.com" + } + ], + "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 number of items. 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", + "readmeFilename": "README.md", + "_id": "lru-cache@2.0.4", + "_from": "lru-cache@~2.0.0" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/test/basic.js new file mode 100644 index 0000000..4200272 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,267 @@ +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: `.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() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/LICENSE new file mode 100644 index 0000000..0c44ae7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/README.md new file mode 100644 index 0000000..7e36512 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/README.md @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/bench.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/bench.js new file mode 100644 index 0000000..5acfd6d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/bench.js @@ -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 +**/ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/package.json new file mode 100644 index 0000000..92a63e9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/package.json @@ -0,0 +1,38 @@ +{ + "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", + "_id": "sigmund@1.0.0", + "_from": "sigmund@~1.0.0" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/sigmund.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/sigmund.js new file mode 100644 index 0000000..82c7ab8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/sigmund.js @@ -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: diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/test/basic.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/test/basic.js new file mode 100644 index 0000000..50c53a1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/node_modules/sigmund/test/basic.js @@ -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() +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/package.json new file mode 100644 index 0000000..3365956 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/package.json @@ -0,0 +1,36 @@ +{ + "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.9", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "~2.0.0", + "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!\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### 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. **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 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\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", + "readmeFilename": "README.md", + "_id": "minimatch@0.2.9", + "_from": "minimatch@0.2" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/basic.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/basic.js new file mode 100644 index 0000000..d860d8b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/basic.js @@ -0,0 +1,297 @@ +// 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"] ] + + // 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' ] ] + + ].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() + 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 +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/brace-expand.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/brace-expand.js similarity index 100% rename from node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/brace-expand.js rename to node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/brace-expand.js diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/caching.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/caching.js similarity index 100% rename from node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/caching.js rename to node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/caching.js diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/defaults.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/defaults.js similarity index 100% rename from node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/defaults.js rename to node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/defaults.js diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/package.json new file mode 100644 index 0000000..9652390 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/package.json @@ -0,0 +1,36 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "name": "glob", + "description": "a little globber", + "version": "3.1.14", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-glob.git" + }, + "main": "glob.js", + "engines": { + "node": "*" + }, + "dependencies": { + "minimatch": "0.2", + "graceful-fs": "~1.1.2", + "inherits": "1" + }, + "devDependencies": { + "tap": "~0.3", + "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} 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} 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} 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", + "_id": "glob@3.1.14", + "_from": "glob@>= 3.1.4" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js new file mode 100644 index 0000000..2b60643 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js @@ -0,0 +1,61 @@ +// 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() + }) + }) + }) +}) + +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, function (er) { + t.ifError(er, "make symlink") + t.end() + }) + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js new file mode 100644 index 0000000..a052ae8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js @@ -0,0 +1,118 @@ +// basic test +// show that it does the same thing by default as the shell. +var tap = require("tap") +, child_process = require("child_process") + +// put more patterns here. +, globs = + ["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/**" + ,"{./*/*,/usr/local/*}" + ,"{/*,*}" // evil owl face! how you taunt me! + ] +, 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 echoOutput + tap.test(pattern, function (t) { + var bashPattern = pattern + , cmd = "shopt -s globstar && " + + "shopt -s extglob && " + + "shopt -s nullglob && " + + // "shopt >&2; " + + "eval \'for i in " + bashPattern + "; do echo $i; done\'" + , cp = child_process.spawn("bash", ["-c",cmd]) + , out = [] + , globResult + cp.stdout.on("data", function (c) { + out.push(c) + }) + cp.stderr.on("data", function (c) { + process.stderr.write(c) + }) + cp.on("close", function () { + echoOutput = flatten(out) + if (!echoOutput) echoOutput = [] + else { + echoOutput = echoOutput.split(/\r*\n/).map(function (m) { + // Bash is a oddly inconsistent with slashes in the + // the results. This implementation is a bit more + // normalized. Account for this in the test results. + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort) + } + next() + }) + + glob(pattern, function (er, matches) { + // sort and unpark, just to match the shell results + matches = matches.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) + + t.ifError(er, pattern + " should not error") + globResult = matches + next() + }) + + function next () { + if (!echoOutput || !globResult) return + + t.deepEqual(globResult, echoOutput, "should match shell") + t.end() + } + }) + + tap.test(pattern + " sync", function (t) { + var matches = glob.sync(pattern).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) + + t.deepEqual(matches, echoOutput, "should match shell") + t.end() + }) +}) + +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() +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js new file mode 100644 index 0000000..352c27e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js @@ -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() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js new file mode 100644 index 0000000..fda66f8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js @@ -0,0 +1,63 @@ +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 + t.same(results, [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/', + 'a/symlink/' ]) + t.end() + }) +}) + +test("mark=false, no / on pattern", function (t) { + glob("a/*", function (er, results) { + if (er) + throw er + t.same(results, [ 'a/abcdef', + 'a/abcfed', + 'a/b', + 'a/bc', + 'a/c', + 'a/cb', + 'a/symlink' ]) + t.end() + }) +}) + +test("mark=true, / on pattern", function (t) { + glob("a/*/", {mark: true}, function (er, results) { + if (er) + throw er + t.same(results, [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/', + 'a/symlink/' ]) + t.end() + }) +}) + +test("mark=false, / on pattern", function (t) { + glob("a/*/", function (er, results) { + if (er) + throw er + t.same(results, [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/', + 'a/symlink/' ]) + t.end() + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js new file mode 100644 index 0000000..c848ed2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js @@ -0,0 +1,106 @@ +// 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)/**" +, 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) +} + +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() +} +var bashResults +tap.test("get bash output", function (t) { + var bashPattern = pattern + , cmd = "shopt -s globstar && " + + "shopt -s extglob && " + + "shopt -s nullglob && " + + // "shopt >&2; " + + "eval \'for i in " + bashPattern + "; do echo $i; done\'" + , cp = child_process.spawn("bash", ["-c",cmd]) + , out = [] + , globResult + cp.stdout.on("data", function (c) { + out.push(c) + }) + cp.stderr.on("data", function (c) { + process.stderr.write(c) + }) + cp.on("close", function () { + bashResults = flatten(out) + if (!bashResults) return t.fail("Didn't get results from bash") + else { + bashResults = cleanResults(bashResults.split(/\r*\n/)) + } + t.ok(bashResults.length, "got some results") + t.end() + }) +}) + +var globResults = [] +tap.test("use a Glob object, and pause/resume it", function (t) { + var g = new Glob(pattern) + , paused = false + , res = [] + + 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, bashResults, + "glob matches should be the same as bash results") + + t.end() + }) +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js new file mode 100644 index 0000000..3ac5979 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js @@ -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() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js new file mode 100644 index 0000000..5ccdd0e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js @@ -0,0 +1,43 @@ +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: '.' }, function (er, matches) { + t.ifError(er) + t.like(matches, []) + t.end() + }) + }) + + t.test('a', function (t) { + glob('/b*/**', { globDebug: true, root: path.resolve('a') }, 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) + })) + 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) + })) + t.end() + }) + }) + + t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() + }) + + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js new file mode 100644 index 0000000..e085f0f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js @@ -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() + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/package.json new file mode 100755 index 0000000..a6b36b2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/package.json @@ -0,0 +1,54 @@ +{ + "name": "cli", + "description": "A tool for rapidly building command line apps", + "version": "0.4.3", + "homepage": "http://github.com/chriso/cli", + "keywords": [ + "cli", + "command line", + "opts", + "parseopt", + "opt", + "args", + "console", + "argsparse", + "optparse", + "daemon", + "autocomplete", + "command", + "autocompletion" + ], + "author": { + "name": "Chris O'Hara", + "email": "cohara87@gmail.com" + }, + "main": "cli.js", + "bugs": { + "mail": "cohara87@gmail.com", + "url": "http://github.com/chriso/cli/issues" + }, + "repository": { + "type": "git", + "url": "http://github.com/chriso/cli.git" + }, + "dependencies": { + "glob": ">= 3.1.4" + }, + "contributors": [ + { + "name": "Douglas Meyer" + } + ], + "engines": { + "node": ">=0.2.5" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "readme": "**cli is a toolkit for rapidly building command line apps - it includes:**\n\n- Full featured opts/args parser\n- Plugin support for adding common options and switches\n- Helper methods for working with input/output and spawning child processes\n- Output colored/styled messages, [progress bars](https://github.com/chriso/cli/blob/master/examples/progress.js) or [spinners](https://github.com/chriso/cli/blob/master/examples/spinner.js)\n- Command [auto-completion](https://github.com/chriso/cli/blob/master/examples/command.js) and [glob support](https://github.com/chriso/cli/blob/master/examples/glob.js)\n\nInstall using `npm install cli` or just bundle [cli.js](https://github.com/chriso/cli/raw/master/cli-min.js) with your app.\n\n## Example apps\n\n### sort.js\n\n```javascript\n#!/usr/bin/env node\nrequire('cli').withStdinLines(function(lines, newline) {\n this.output(lines.sort().join(newline));\n});\n```\n\nTry it out\n\n```bash\n$ ./sort.js < input.txt\n```\n\nLet's add support for an `-n` switch to use a numeric sort, and a `-r` switch to reverse output - only 5 extra lines of code (!)\n\n```javascript\nvar cli = require('cli'), options = cli.parse();\n\ncli.withStdinLines(function(lines, newline) {\n lines.sort(!options.n ? null : function(a, b) {\n return parseInt(a) > parseInt(b);\n });\n if (options.r) lines.reverse();\n this.output(lines.join(newline));\n});\n```\n\n### static.js\n\nLet's create a static file server with daemon support to see the opts parser + plugins in use - note: this requires `npm install creationix daemon`\n\n```javascript\nvar cli = require('cli').enable('daemon', 'status'); //Enable 2 plugins\n\ncli.parse({\n log: ['l', 'Enable logging'],\n port: ['p', 'Listen on this port', 'number', 8080],\n serve: [false, 'Serve static files from PATH', 'path', './public']\n});\n\ncli.main(function(args, options) {\n var server, middleware = [];\n\n if (options.log) {\n this.debug('Enabling logging');\n middleware.push(require('creationix/log')());\n }\n\n this.debug('Serving files from ' + options.serve);\n middleware.push(require('creationix/static')('/', options.serve, 'index.html'));\n\n server = this.createServer(middleware).listen(options.port);\n\n this.ok('Listening on port ' + options.port);\n});\n```\n\nTo output usage information\n\n```bash\n$ ./static.js --help\n```\n\nTo create a daemon that serves files from */tmp*, run\n\n```bash\n$ ./static.js -ld --serve=/tmp\n```\n\nFor more examples, see [./examples](https://github.com/chriso/cli/tree/master/examples)\n\n## Helper methods\n\ncli has methods that collect stdin (newline is autodetected as \\n or \\r\\n)\n\n```javascript\ncli.withStdin(callback); //callback receives stdin as a string\ncli.withStdinLines(callback); //callback receives stdin split into an array of lines (lines, newline)\n```\n\ncli also has a lower level method for working with input line by line (see [./examples/cat.js](https://github.com/chriso/cli/blob/master/examples/cat.js) for an example). \n\n```javascript\ncli.withInput(file, function (line, newline, eof) {\n if (!eof) {\n this.output(line + newline);\n }\n});\n```\n\n*Note: `file` can be omitted if you want to work with stdin*\n\nTo output a progress bar, call\n\n```javascript\ncli.progress(progress); //Where 0 <= progress <= 1\n```\n\nTo spawn a child process, use\n\n```javascript\ncli.exec(cmd, callback); //callback receives the output of the process (split into lines)\n```\n\ncli also comes bundled with kof's [node-natives](https://github.com/kof/node-natives) (access with cli.native) and creationix' [stack](https://github.com/creationix/stack) (access with cli.createServer)\n\n## Plugins\n\nPlugins are a way of adding common opts and can be enabled using \n\n```javascript\ncli.enable(plugin1, [plugin2, ...]); //To disable, use the equivalent disable() method\n```\n\n**help** - *enabled by default*\n\nAdds `-h,--help` to output auto-generated usage information\n\n**version**\n\nAdds `-v,--version` to output version information for the app. cli will attempt to locate and parse a nearby *package.json*\n\nTo set your own app name and version, use `cli.setApp(app_name, version)`\n\n**status**\n\nAdds options to show/hide the stylized status messages that are output to the console when using one of these methods\n\n```javascript\ncli.debug(msg); //Only shown when using --debug\ncli.error(msg);\ncli.fatal(msg); //Exits the process after outputting msg\ncli.info(msg);\ncli.ok(msg);\n```\n\n`-k,--no-color` will omit ANSI color escapes from the output\n\n**glob** - *requires* `npm install glob`\n\nEnables glob matching of arguments\n\n**daemon** - *requires* `npm install daemon`\n\nAdds `-d,--daemon ARG` for daemonizing the process and controlling the resulting daemon\n\n`ARG` can be either start (default), stop, restart, pid (outputs the daemon's pid if it's running), or log (output the daemon's stdout+stderr)\n\n**timeout**\n\nAdds `-t,--timeout N` to exit the process after N seconds with an error\n\n**catchall**\n\nAdds `-c,--catch` to catch and output uncaughtExceptions and resume execution\n\n*Note: Plugins are automatically disabled if an option or switch of the same name is already defined*\n\n## LICENSE\n\n(MIT license)\n\nCopyright (c) 2010 Chris O'Hara \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\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "_id": "cli@0.4.3", + "_from": "cli@0.4.3" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/README.md index 6fd07d2..2664c08 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/README.md @@ -23,141 +23,53 @@ minimatch("bar.foo", "*.bar") // false! ## Features -Supports these glob features: - -* Brace Expansion -* Extended glob matching -* "Globstar" `**` matching +Supports all glob features. See: * `man sh` -* `man bash` -* `man 3 fnmatch` +* `man fnmatch` * `man 5 gitignore` -### 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. +### Departures from zsh/bash/ksh/sh -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 the pattern starts with a `!` character, then it is negated. 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. +will not match anything. (Use `\#` to match a literal `#` at the +start of a line.) -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.** +The double-star `**` is always supported, instead of requiring a special +flag. -If an escaped pattern has no matches, and the `nonull` flag is set, +If an escaped pattern has no matches, and the `null` flag is not 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. - - -## 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. +`"*a?"`. ## 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 }) -``` +Main export. Tests a path against +the pattern using the options. ### 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})) -``` +supplied argument, suitable for use with `Array.filter`. ### 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})) -``` +files, in the style of fnmatch or glob. If nothing is matched, then +return the pattern (unless `{ null: true }` in the options.) ### minimatch.makeRe(pattern, options) -Make a regular expression object from the pattern. +Make a regular expression object +from the pattern. ## Options @@ -167,52 +79,36 @@ All options are `false` by default. 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. +### null -### 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)`. +Return an empty list from minimatch.match, instead of a list +containing the pattern itself. ### nocase Perform a case-insensitive match. -### nonull +### cache -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. +An LRU cache with `.get(k)` and `.set(k,v)` methods. By +default, an instance of `node-lru-cache` is used, with 1000 max +entries. + +### slash + +If set, then `a/*` will match `a/` as well as `a/b`. ### 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 +`a?b` would match `xyz/123/acb`. -Suppress the behavior of treating `#` at the start of a pattern as a -comment. +### partial -### nonegate +Internal. Used by `minimatch.makeRe`. -Suppress the behavior of treating a leading `!` character as negation. - -### flipNegate +### dot -Returns from negate expressions the same as if they were not negated. -(Ie, true on a hit, false on a miss.) +Allow patterns to match paths starting with a period, even if +the pattern does not explicitly start with a period. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/blerg.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/blerg.js new file mode 100644 index 0000000..9eb56e2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/blerg.js @@ -0,0 +1,62 @@ + +// Turn something like {a,b{c,d},}x{e,f} into +// ["axe", "axf", "bcxe", "bcxf", "bdxe", "bdxf", "xe", "xf"] +// Only {,} groups are expanded. While in many cases {x,y} is +// functionally equivalent to @(x|y), for the purpose of globbing +// files, only {x,y} gets expanded as multiple patterns. +minimatch.patternSet = patternSet +function patternSet (pattern) { + if (!pattern.match(/{/) || !pattern.match(/}/)) { + // shortcut - no sets. + return [pattern] + } + + // a{b,c{d,e},{f,g}h}x{y,z} + // + // t=[before set, set, after set] + // t=["a", ["b", "c{d,e}", "{f,g}h"], "x{y,z}"] + + // start walking, and note the position of the first { + // and the corresponding } + var p = pattern.indexOf("{") + , l = pattern.length + , d = 0 + , escaping = false + , inClass = false + while (++ p < l) { + switch (pattern.charAt(p)) { + case "{": + d ++ + continue + case "}": + + + + // t[2] = patternSet(t[2]) + // t = [t[0]].concat([t[1].map(patternSet)]).concat([t[2]]) + // + // t=["a",[["b"],[["cd","ce"]],[["fh","gh"]]],["xy","xz"]] + // + // // first turn into + // // [["ab"], ["acd", "ace"], ["afh", "agh"]] + // return t[1].map(function (p) { + // return p.map(function (p) { + // return t[0] + p + // }) + // }) + // // flatten into ["ab", "acd", "ace", "afh", "agh"] + // .reduce(function (l, r) { + // return l.concat(r) + // }, []) + // // tack all the endings onto each one + // .map(function (p) { + // return t[2].map(function (e) { + // return p + e + // }) + // }) + // // flatten again + // .reduce(function (l, r) { + // return l.concat(r) + // }, []) +} + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/minimatch.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/minimatch.js index a2221ee..c50ab71 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/minimatch.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/minimatch.js @@ -1,493 +1,98 @@ -;(function (require, exports, module, platform) { +// This is a JavaScript implementation of the fnmatch-like +// stuff that git uses in its .gitignore files. +// See `man 5 gitignore`. -if (module) module.exports = minimatch -else exports.minimatch = minimatch - -if (!require) { - require = function (id) { - switch (id) { - 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 = {} +module.exports = minimatch 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})($|\\\/)).)*?" + , LRU = require("lru-cache") - // 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.monkeyPatch = monkeyPatch -function monkeyPatch () { - var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") - var orig = desc.value - desc.value = function (p) { - if (p instanceof Minimatch) return p.match(this) - return orig.call(this, p) - } - Object.defineProperty(String.prototype, desc) -} - -minimatch.filter = filter -function filter (pattern, options) { +minimatch.filter = function (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)) - } +minimatch.match = function (list, pattern, options) { + if (!options) options = {} + var ret = list.filter(minimatch.filter(pattern, options)) + if (options.debug) console.error("\nmatch: %s %j %j", pattern, list, ret) - m.Minimatch = function Minimatch (pattern, options) { - return new orig.Minimatch(pattern, ext(def, options)) + // set the null flag to allow empty match sets + // Note that minimatch itself, and filter(), do not + // respect this flag, only minimatch.match(list, pattern) does. + if (!options.null && !ret.length) { + return [pattern] } - return m -} - -Minimatch.defaults = function (def) { - if (!def || !Object.keys(def).length) return Minimatch - return minimatch.defaults(def).Minimatch + return ret } - function minimatch (p, pattern, options) { if (typeof pattern !== "string") { throw new TypeError("glob pattern string required") } - if (!options) options = {} + options = options || {} - // shortcut: comments match nothing. - if (!options.nocomment && pattern.charAt(0) === "#") { - return false - } + // to set the cache, just replace with a different obj + // supporting set(k,v) and v=get(k) methods. + var cache = options.cache || minimatch.cache + if (!cache) cache = minimatch.cache = new LRU(1000) // "" 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() - - // 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" + Object.keys(options).filter(function (k) { - return options[k] - }).join(":") - 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.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) console.error(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) - }) - - if (options.debug) console.error(this.pattern, set) - - // glob --> regexps - set = set.map(function (s, si, set) { - return s.map(this.parse, this) - }, this) - - if (options.debug) console.error(this.pattern, set) - - // filter out everything that didn't compile properly. - set = set.filter(function (s) { - return -1 === s.indexOf(false) - }) - - if (options.debug) console.error(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) !== "{") { - // console.error(pattern) - var prefix = null - for (var i = 0, l = pattern.length; i < l; i ++) { - var c = pattern.charAt(i) - // console.error(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) { - // console.error("no sets") - return [pattern] - } - - var tail = braceExpand(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) { - // console.error("numset", numset[1], numset[2]) - var suf = braceExpand(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 = "" - } - - // console.error("Entering for") - FOR: for (i = 1, l = pattern.length; i < l; i ++) { - var c = pattern.charAt(i) - // console.error("", 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) { - // console.error("didn't close", pattern) - return braceExpand("\\" + pattern, options) - } - - // x{y,z} -> ["xy", "xz"] - // console.error("set", set) - // console.error("suffix", pattern.substr(i)) - var suf = braceExpand(pattern.substr(i), options) - // ["b", "c{d,e}","{f,g}h"] -> - // [["b"], ["cd", "ce"], ["fh", "gh"]] - var addBraces = set.length === 1 - // console.error("set pre-expanded", set) - set = set.map(function (p) { - return braceExpand(p, options) - }) - // console.error("set expanded", set) + if (!pattern) return p === "" + // comments. + if (pattern.trim().charAt(0) === "#") return false - // [["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 + "}" - }) + // check the cache + var re = cache.get(pattern + "\n" + JSON.stringify(options)) + if (!re && re !== false) { + cache.set(pattern, re = minimatch.makeRe(pattern, options)) } - // 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 + if (options.debug) { + console.error(pattern + "\t" + re, JSON.stringify(p)) + } + + // some kind of invalid thing + if (!re) return false + + + // patterns that end in / can only match dirs + // however, dirs also match the same thing that *doesn't* + // end in a slash. + var match = + // a/ should not match a/*, but will match */ + // accomplish this by not applying the regexp + // directly, unless the pattern would match + // trailing slash'ed things, or the thing isn't + // a trailing slash, or slashes are opted-in + ( ( options.slash || + p.substr(-1) !== "/" || + pattern.substr(-1) === "/" ) + && !!p.match(re) ) + + // a/ should match * or a + || ( p.substr(-1) === "/" && + !!p.slice(0, -1).match(re) ) + + // a pattern with *no* slashes will match against + // either the full path, or just the basename. + || ( options.matchBase && + pattern.indexOf("/") === -1 && + path.basename(p).match(re) ) + + //console.error(" MINIMATCH: %j %j %j %j", + // re.toString(), pattern, p, match) + return match } -// 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 = false - , 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}(?:$|\\\/))" - : "(?!\\.)" +minimatch.makeRe = makeRe +function makeRe (pattern, options) { + options = options || {} function clearStateChar () { if (stateChar) { @@ -495,12 +100,10 @@ function parse (pattern, isSub) { // that wasn't consumed by this pass. switch (stateChar) { case "*": - re += star - hasMagic = true + re += oneStar break case "?": - re += qmark - hasMagic = true + re += "." break default: re += "\\"+stateChar @@ -510,6 +113,27 @@ function parse (pattern, isSub) { } } + var braceDepth = 0 + , re = "" + , escaping = false + , oneStar = options.dot ? "[^\\/]*?" + : "(?:(?!(?:\\\/|^)\\.)[^\\/])*?" + , twoStar = options.dot ? ".*?" + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + : "(?:(?!(?:\\\/|^)\\.).)*?" + , reSpecials = "().*{}+?[]^$/\\" + , patternListStack = [] + , stateChar + , negate = false + , negating = false + , inClass = false + , reClassStart = -1 + , classStart = -1 + , classStartPattern = options.dot ? "" + : "(?:(?!(?:\\\/|^)\\.)" + , classEndPattern = options.dot ? "" : ")" + for ( var i = 0, len = pattern.length, c ; (i < len) && (c = pattern.charAt(i)) ; i ++ ) { @@ -518,120 +142,119 @@ function parse (pattern, isSub) { console.error("%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 - + switch (c) { case "\\": - clearStateChar() - escaping = true + if (stateChar) { + if (stateChar === "*") re += oneStar + else re += "\\" + stateChar + stateChar = false + } + if (escaping) { + re += "\\\\" // must match literal \ + escaping = false + } else { + escaping = true + } continue // the various stateChar values - // for the "extglob" stuff. - case "?": - case "*": - case "+": - case "@": case "!": - if (options.debug) { - console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + if (i === 0 || negating) { + negate = !negate + negating = true + break + } else { + negating = false } + // fallthrough + case "+": + case "@": + case "*": + case "?": + if (options.debug) { + console.error("%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) { - if (c === "!" && i === classStart + 1) c = "^" + negating = false + if (escaping) { + re += "\\" + c + escaping = false + } else if (inClass) { re += c - continue + } else if (c === "*" && stateChar === "*") { // ** + re += twoStar + stateChar = false + } else { + if (stateChar) { + if (stateChar === "*") re += oneStar + else if (stateChar === "?") re += "." + else re += "\\" + stateChar + } + stateChar = c } - - // 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. - 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) { + if (escaping) { + re += "\\(" + escaping = false + } else if (inClass) { re += "(" - continue - } - - if (!stateChar) { + } else if (stateChar) { + plType = stateChar + patternListStack.push(plType) + re += stateChar === "!" ? "(?!" : "(?:" + stateChar = false + } else { re += "\\(" - continue } - - plType = stateChar - patternListStack.push({ type: plType - , start: i - 1 - , reStart: re.length }) - // negation is (?:(?!js)[^/]*) - re += stateChar === "!" ? "(?:(?!" : "(?:" - stateChar = false continue case ")": - if (inClass || !patternListStack.length) { + if (escaping || inClass) { + re += "\\)" + escaping = false + } else if (patternListStack.length) { + re += ")" + plType = patternListStack.pop() + switch (plType) { + case "?": + case "+": + case "*": re += plType + case "!": + case "@": break + } + } else { re += "\\)" - continue - } - - hasMagic = true - re += ")" - plType = patternListStack.pop().type - // negation is (?:(?!js)[^/]*) - // The others are (?:) - switch (plType) { - case "!": - re += "[^/]*?)" - break - case "?": - case "+": - case "*": re += plType - case "@": break // the default anyway } continue case "|": - if (inClass || !patternListStack.length || escaping) { + if (escaping || inClass) { re += "\\|" escaping = false - continue + } else if (patternListStack.length) { + re += "|" + } else { + re += "\\|" } - - re += "|" continue - // these are mostly the same in regexp and glob + // these are mostly the same in regexp and glob :) case "[": // swallow any state-tracking char before the [ clearStateChar() - if (inClass) { + if (escaping || inClass) { re += "\\" + c - continue + escaping = false + } else { + inClass = true + classStart = i + reClassStart = re.length + re += classStartPattern + re += c } - - inClass = true - classStart = i - reClassStart = re.length - re += c continue case "]": @@ -639,16 +262,48 @@ function parse (pattern, isSub) { // 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) { + if (i === classStart + 1) escaping = true + + if (escaping || !inClass) { re += "\\" + c escaping = false - continue + } else { + inClass = false + re += c + classEndPattern } + continue - // finish up the class. - hasMagic = true - inClass = false - re += c + case "{": + if (escaping || inClass) { + re += "\\{" + escaping = false + } else { + re += "(?:" + braceDepth ++ + } + continue + + case "}": + if (escaping || inClass || braceDepth === 0) { + re += "\\}" + escaping = false + } else { + // swallow any state char that wasn't consumed + clearStateChar() + re += ")" + braceDepth -- + } + continue + + case ",": + if (escaping || inClass || braceDepth === 0) { + re += "," + escaping = false + } else { + // swallow any state char that wasn't consumed + clearStateChar() + re += "|" + } continue default: @@ -658,7 +313,7 @@ function parse (pattern, isSub) { if (escaping) { // no need escaping = false - } else if (reSpecials[c] + } else if (reSpecials.indexOf(c) !== -1 && !(c === "^" && inClass)) { re += "\\" } @@ -666,387 +321,52 @@ function parse (pattern, isSub) { re += c } // switch + + if (negating && c !== "!") negating = false + } // for + // handle trailing things that only matter at the very end. + if (stateChar) { + clearStateChar() + } else if (escaping) { + re += "\\\\" + } - // 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] - } + var cs = re.substr(reClassStart + classStartPattern.length + 1) + , csOpts = Object.create(options) + csOpts.partial = true - // 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 + "|" - }) - - // console.error("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 + re = re.substr(0, reClassStart) + "\\[" + + makeRe(cs, csOpts) } - // 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("|") + if (options.partial) return re // 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 + ").*$" + // fail on the pattern, but allow anything otherwise. + if (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) { - // console.error("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) - if (options.debug) { - console.error(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 - // console.error(this.pattern, "set", set) - - for (var i = 0, l = set.length; i < l; i ++) { - var pattern = set[i] - var hit = this.matchOne(f, 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 + // really insane glob patterns can cause bad things. + var flags = "" + if (options.nocase) flags += "i" if (options.debug) { - console.error("matchOne", - { "this": this - , file: file - , pattern: pattern }) - } - - if (options.matchBase && pattern.length === 1) { - file = path.basename(file.join("/")).split("/") + console.error("/%s/%s", re, flags) } - if (options.debug) { - console.error("matchOne", file.length, pattern.length) - } - - for ( var fi = 0 - , pi = 0 - , fl = file.length - , pl = pattern.length - ; (fi < fl) && (pi < pl) - ; fi ++, pi ++ ) { - - if (options.debug) { - console.error("matchOne loop") - } - var p = pattern[pi] - , f = file[fi] - - if (options.debug) { - console.error(pattern, p, f) - } - - // should be impossible. - // some invalid regexp stuff in the set. - if (p === false) return false - - if (p === GLOBSTAR) { - // "**" - // 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/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) { - // 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] - if (swallowee === "." || swallowee === ".." || - (!options.dot && swallowee.charAt(0) === ".")) { - // console.error("dot detected!") - break WHILE - } - - // XXX remove this slice. Just pass the start index. - if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { - // found a match. - return true - } else { - // ** swallows 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 - // console.error("\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 - } - if (options.debug) { - console.error("string match", p, f, hit) - } - } else { - hit = f.match(p) - if (options.debug) { - console.error("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 + try { + return new RegExp(re, flags) + } catch(ex) { + return false } - - // 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" - ) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md index 8ea0dd9..0f3908d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md @@ -2,45 +2,13 @@ A cache object that deletes the least-recently-used items. -## Usage: +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 + var LRU = require("lru-cache") + , cache = LRU(10) // max 10 items. default = Infinity + cache.set("key", "value") + cache.get("key") // "value" -cache.set("key", "value") -cache.get("key") // "value" + cache.reset() // empty the cache -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 number of items. 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. +RTFS for more info. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js index 8b6ed8c..c3e4feb 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -4,110 +4,49 @@ if (module) { module.exports = LRUCache } else { // just set the global for non-node platforms. - this.LRUCache = LRUCache + ;(function () { return this })().LRUCache = LRUCache } function hOP (obj, key) { return Object.prototype.hasOwnProperty.call(obj, key) } -function naiveLength () { return 1 } - -function LRUCache (options) { +function LRUCache (maxLength) { if (!(this instanceof LRUCache)) { - return new LRUCache(options) - } - - var max - if (typeof options === 'number') { - max = options - options = {max: max} - } - max = options.max - - if (!options) options = {} - - var lengthCalculator = options.length || naiveLength - - if (typeof lengthCalculator !== "function") { - lengthCalculator = naiveLength - } - if (!max || !(typeof max === "number") || max <= 0 ) { - max = Infinity + return new LRUCache(maxLength) } - - var maxAge = options.maxAge || null - - var dispose = options.dispose - var cache = {} // hash of items by key , lruList = {} // list of items in order of use recency , lru = 0 // least recently used , mru = 0 // most recently used , length = 0 // number of items in the list - , itemCount = 0 - - // resize the cache when the max changes. - Object.defineProperty(this, "max", + // resize the cache when the maxLength changes. + Object.defineProperty(this, "maxLength", { set : function (mL) { if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity - max = mL - // if it gets above double max, trim right away. + maxLength = mL + // if it gets above double maxLength, trim right away. // otherwise, do it whenever it's convenient. - if (length > max) trim() + if (length > maxLength) trim() } - , get : function () { return max } + , get : function () { return maxLength } , enumerable : true }) - // resize the cache when the lengthCalculator changes. - Object.defineProperty(this, "lengthCalculator", - { set : function (lC) { - if (typeof lC !== "function") { - lengthCalculator = naiveLength - length = itemCount - Object.keys(cache).forEach(function (key) { - cache[key].length = 1 - }) - } else { - lengthCalculator = lC - length = 0 - Object.keys(cache).forEach(function (key) { - cache[key].length = lengthCalculator(cache[key].value) - length += cache[key].length - }) - } - - if (length > max) trim() - } - , get : function () { return lengthCalculator } - , enumerable : true - }) + this.maxLength = maxLength Object.defineProperty(this, "length", { get : function () { return length } , enumerable : true }) - - Object.defineProperty(this, "itemCount", - { get : function () { return itemCount } - , enumerable : true - }) - this.reset = function () { - if (dispose) { - Object.keys(cache).forEach(function (k) { - dispose(k, cache[k].value) - }) - } cache = {} lruList = {} lru = 0 mru = 0 length = 0 - itemCount = 0 } // Provided for debugging/dev purposes only. No promises whatsoever that @@ -118,40 +57,19 @@ function LRUCache (options) { this.set = function (key, value) { if (hOP(cache, key)) { - // dispose of the old one before overwriting - if (dispose) dispose(key, cache[key].value) - if (maxAge) cache[key].now = Date.now() - cache[key].value = value this.get(key) - return true - } - - var hit = { - key:key, - value:value, - lu:mru++, - length:lengthCalculator(value), - now: (maxAge) ? Date.now() : 0 + cache[key].value = value + return undefined } - - // oversized objects fall out of cache automatically. - if (hit.length > max) return false - - length += hit.length + var hit = {key:key, value:value, lu:mru++} lruList[hit.lu] = cache[key] = hit - itemCount ++ - - if (length > max) trim() - return true + length ++ + if (length > maxLength) trim() } this.get = function (key) { - if (!hOP(cache, key)) return + if (!hOP(cache, key)) return undefined var hit = cache[key] - if (maxAge && (Date.now() - hit.now > maxAge)) { - this.del(key) - return - } delete lruList[hit.lu] if (hit.lu === lru) lruWalk() hit.lu = mru ++ @@ -160,34 +78,27 @@ function LRUCache (options) { } this.del = function (key) { - if (!hOP(cache, key)) return + if (!hOP(cache, key)) return undefined var hit = cache[key] - if (dispose) dispose(key, hit.value) delete cache[key] delete lruList[hit.lu] if (hit.lu === lru) lruWalk() - length -= hit.length - itemCount -- + length -- } function lruWalk () { // lru has been deleted, hop up to the next hit. - for (var key in lruList) { - return key - } + lru = Object.keys(lruList).shift() } function trim () { - if (length <= max) return - var prune = Object.keys(lruList) - for (var i = 0; i < prune.length && length > max; i ++) { - var hit = lruList[prune[i]] - if (dispose) dispose(hit.key, hit.value) - length -= hit.length - delete cache[ hit.key ] + if (length <= maxLength) return undefined + var prune = Object.keys(lruList).slice(0, length - maxLength) + for (var i = 0, l = (length - maxLength); i < l; i ++) { + delete cache[ lruList[prune[i]].key ] delete lruList[prune[i]] } - + length = maxLength lruWalk() } } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json index 9428d83..238aab2 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json @@ -1,7 +1,7 @@ { "name": "lru-cache", "description": "A cache object that deletes the least-recently-used items.", - "version": "2.0.2", + "version": "1.0.6", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me" @@ -15,43 +15,14 @@ "url": "git://github.com/isaacs/node-lru-cache.git" }, "devDependencies": { - "tap": "" + "tap": "0" }, "license": { "type": "MIT", "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" }, - "contributors": [ - { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me" - }, - { - "name": "Carlos Brito Lage", - "email": "carlos@carloslage.net" - }, - { - "name": "Marko Mikulicic", - "email": "marko.mikulicic@isti.cnr.it" - }, - { - "name": "Trent Mick", - "email": "trentm@gmail.com" - }, - { - "name": "Kevin O'Hara", - "email": "kevinohara80@gmail.com" - }, - { - "name": "Marco Rogers", - "email": "marco.rogers@gmail.com" - }, - { - "name": "Jesse Dailey", - "email": "jesse.dailey@gmail.com" - } - ], - "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 number of items. 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", - "_id": "lru-cache@2.0.2", - "_from": "lru-cache@~2.0.0" + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\nUsage:\n\n var LRU = require(\"lru-cache\")\n , cache = LRU(10) // max 10 items. default = Infinity\n cache.set(\"key\", \"value\")\n cache.get(\"key\") // \"value\"\n\n cache.reset() // empty the cache\n\nRTFS for more info.\n", + "readmeFilename": "README.md", + "_id": "lru-cache@1.0.6", + "_from": "lru-cache@~1.0.2" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js index d04af0b..f6d7a6d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -1,17 +1,17 @@ -var test = require("tap").test - , LRU = require("../") +var test = require('tap').test + , LRU = require('../') -test("basic", function (t) { - var cache = new LRU({max: 10}) +test('basic', function (t) { + var cache = new LRU(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.equal(cache.maxLength, 10) t.end() }) -test("least recently set", function (t) { +test('least recently set', function (t) { var cache = new LRU(2) cache.set("a", "A") cache.set("b", "B") @@ -22,7 +22,7 @@ test("least recently set", function (t) { t.end() }) -test("lru recently gotten", function (t) { +test('lru recently gotten', function (t) { var cache = new LRU(2) cache.set("a", "A") cache.set("b", "B") @@ -34,7 +34,7 @@ test("lru recently gotten", function (t) { t.end() }) -test("del", function (t) { +test('del', function (t) { var cache = new LRU(2) cache.set("a", "A") cache.del("a") @@ -42,17 +42,17 @@ test("del", function (t) { t.end() }) -test("max", function (t) { +test('maxLength', function (t) { var cache = new LRU(3) - // test changing the max, verify that the LRU items get dropped. - cache.max = 100 + // test changing the maxLength, verify that the LRU items get dropped. + cache.maxLength = 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 + cache.maxLength = 3 t.equal(cache.length, 3) for (var i = 0; i < 97; i ++) { t.equal(cache.get(i), undefined) @@ -61,15 +61,15 @@ test("max", function (t) { t.equal(cache.get(i), i) } - // now remove the max restriction, and try again. - cache.max = "hello" + // now remove the maxLength restriction, and try again. + cache.maxLength = "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 + cache.maxLength = 3 t.equal(cache.length, 3) for (var i = 0; i < 97; i ++) { t.equal(cache.get(i), undefined) @@ -80,169 +80,38 @@ test("max", function (t) { t.end() }) -test("reset", function (t) { +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.maxLength, 10) t.equal(cache.get("a"), undefined) t.equal(cache.get("b"), undefined) t.end() }) - // Note: `.dump()` is a debugging tool only. No guarantees are made // about the format/layout of the response. -test("dump", function (t) { +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 } } + 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.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.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() -}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/package.json index 695530c..9f9a4b0 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/package.json @@ -6,7 +6,7 @@ }, "name": "minimatch", "description": "a glob matcher in javascript", - "version": "0.2.6", + "version": "0.0.5", "repository": { "type": "git", "url": "git://github.com/isaacs/minimatch.git" @@ -19,16 +19,19 @@ "node": "*" }, "dependencies": { - "lru-cache": "~2.0.0" + "lru-cache": "~1.0.2" }, "devDependencies": { - "tap": "" + "tap": "~0.0.5" }, - "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!\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### 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. **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 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\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", - "_id": "minimatch@0.2.6", - "_from": "minimatch@>=0.0.4" + "licenses": [ + { + "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!\n```\n\n## Features\n\nSupports all glob features.\n\nSee:\n\n* `man sh`\n* `man fnmatch`\n* `man 5 gitignore`\n\n### Departures from zsh/bash/ksh/sh\n\nIf the pattern starts with a `!` character, then it is negated.\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.)\n\nThe double-star `**` is always supported, instead of requiring a special\nflag.\n\nIf an escaped pattern has no matches, and the `null` flag is not 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?\"`.\n\n## Functions\n\n### minimatch(path, pattern, options)\n\nMain export. Tests a path against\nthe pattern using the options.\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`.\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, then\nreturn the pattern (unless `{ null: true }` in the options.)\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object\nfrom 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### null\n\nReturn an empty list from minimatch.match, instead of a list\ncontaining the pattern itself.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### cache\n\nAn LRU cache with `.get(k)` and `.set(k,v)` methods. By\ndefault, an instance of `node-lru-cache` is used, with 1000 max\nentries.\n\n### slash\n\nIf set, then `a/*` will match `a/` as well as `a/b`.\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 `xyz/123/acb`.\n\n### partial\n\nInternal. Used by `minimatch.makeRe`.\n\n### dot\n\nAllow patterns to match paths starting with a period, even if\nthe pattern does not explicitly start with a period.\n", + "readmeFilename": "README.md", + "_id": "minimatch@0.0.5", + "_from": "minimatch@0.0.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/t.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/t.js new file mode 100644 index 0000000..e67bf88 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/t.js @@ -0,0 +1,4 @@ +console.error(Object.keys(global).length) +var m = require("./") +console.log(m.makeRe("**")) +console.error(Object.keys(global).length) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/basic.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/basic.js index cf1778a..f4f585f 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/basic.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/basic.js @@ -1,7 +1,4 @@ // 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) @@ -20,30 +17,29 @@ tap.test("basic tests", function (t) { ; [ "http://www.bashcookbook.com/bashinfo" + "/source/bash-1.14.7/tests/glob-test" , ["a*", ["a", "abc", "abd", "abe"]] - , ["X*", ["X*"], {nonull: true}] - + , ["X*", ["X*"]] // allow null glob expansion - , ["X*", []] + , ["X*", [], { null: true }] // 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}] + + , ["\\.\\./*/", ["\\.\\./*/"]] + , ["s/\\..*//", ["s/\\..*//"]] , "legendary larry crashes bashes" , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" - , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"]] , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" - , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"]] , "character classes" , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] @@ -100,6 +96,7 @@ tap.test("basic tests", function (t) { , ["[]]", ["]"], null, ["]"]] , ["[]-]", ["]"], null, ["]"]] , ["[a-\z]", ["p"], null, ["p"]] + , ["[/\\\\]*", ["/tmp"], null, ["/tmp"]] , ["??**********?****?", [], { null: true }, ["abc"]] , ["??**********?****c", [], { null: true }, ["abc"]] , ["?************c****?****", [], { null: true }, ["abc"]] @@ -126,111 +123,12 @@ tap.test("basic tests", function (t) { , "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) @@ -242,16 +140,12 @@ tap.test("basic tests", function (t) { , tapOpts = c[4] || {} // options.debug = true - var m = new mm.Minimatch(pattern, options) - var r = m.makeRe() + var r = mm.makeRe(pattern, options) 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) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/package.json index 4a18a7a..025eee6 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/package.json @@ -1,6 +1,6 @@ { "name": "jshint", - "version": "0.5.9", + "version": "0.9.1", "description": "A CLI for JSHint", "homepage": "http://github.com/jshint/node-jshint", "author": { @@ -23,19 +23,19 @@ "packages/jshint/jshint.js", "README.md", "LICENSE", - "HELP", "bin/hint", "lib" ], "dependencies": { - "argsparser": ">=0.0.3", - "minimatch": ">=0.0.4" + "cli": "0.4.3", + "minimatch": "0.0.x" }, "devDependencies": { - "jasmine-node": "1.0.7" + "jasmine-node": "1.0.x" }, "preferGlobal": true, - "readme": "# node-jshint\n\nA command line interface and npm package for jshint.\n\n## Install\n\nTo use jshint from any location (for npm v1.x) you need to install using the global (-g) flag.\n\n npm install -g jshint\n\n## Usage\n\nThe command line interface looks like this.\n\n jshint path path2 [options]\n\nYou can also require JSHint itself as a module.\n\n var jshint = require('jshint');\n\nNote: If you are using npm v1.x be sure to install jshint locally (without the -g flag) or link it globally.\n\n## Text Editor Plugins\n\n* [gedit-node-jshint](https://github.com/niftylettuce/gedit-node-jshint) - Simply use CTRL+J in gedit to run JSHint using `node-jshint`.\n* [vim syntastic](https://github.com/scrooloose/syntastic) - Run node-jshint at each file save.\n* [sublime-jshint](https://github.com/uipoet/sublime-jshint) - `F7` or `command-B` on any .js file. `F4` next error line,column. `shift-F4` previous error line,column.\n\n## Custom Reporters\n\nSpecify a custom reporter module (see example/reporter.js).\n\n --reporter path/to/reporter.js\n\nUse a jslint compatible xml reporter.\n\n --jslint-reporter\n\nShow additional non-error data generated by jshint (unused globals etc).\n\n --show-non-errors\n\n## Custom Options\n\nSpecify custom lint options (see [example/config.json](https://github.com/jshint/node-jshint/blob/master/example/config.json)).\n\n --config path/to/config.json\n\nNote: This bypasses any .jshintrc files.\n\n## Default Options\n\nThe CLI uses the default options that come with JSHint. However, if it locates a .jshintrc file in your home directory (~/) it will use those options first.\n\n## Per Directory Options\n\nIf there is a .jshintrc file in the current working directory, any of those options will take precedence over (or be merged with) any options found in the ~/.jshintrc file (if it exists).\n\n## Ignoring Files and Directories\n\nIf there is a .jshintignore file in the current working directory, then any directories or files will be skipped over.\n\nNote: Pattern matching uses minimatch, with the nocase [option](https://github.com/isaacs/minimatch). When there is no match, it performs a left side match (when no forward slashes present and path is a directory).\n\n## Installing dependencies for development\n\n ./configure\n\n## Build Commands\n\n jake -T\n", - "_id": "jshint@0.5.9", - "_from": "jshint@~0.5.9" + "readme": "# node-jshint\n\nA command line interface and npm package for jshint.\n\n## Install\n\nTo use jshint from any location (for npm v1.x) you need to install using the global (-g) flag.\n\n npm install -g jshint\n\n## Usage\n\n jshint -h\n\nYou can also require JSHint itself as a module.\n\n var jshint = require('jshint');\n\nNote: If you are using npm v1.x be sure to install jshint locally (without the -g flag) or link it globally.\n\n## Text Editor Plugins\n\n* [gedit-node-jshint](https://github.com/niftylettuce/gedit-node-jshint) - Simply use CTRL+J in gedit to run JSHint using `node-jshint`.\n* [vim syntastic](https://github.com/scrooloose/syntastic) - Run node-jshint at each file save.\n* [sublime-jshint](https://github.com/uipoet/sublime-jshint) - `F7` or `command-B` on any .js file. `F4` next error line,column. `shift-F4` previous error line,column.\n\n## Custom Reporters\n\nSpecify a custom reporter module (see example/reporter.js).\n\n --reporter path/to/reporter.js\n\nUse a jslint compatible xml reporter.\n\n --jslint-reporter\n\nShow additional non-error data generated by jshint (unused globals etc).\n\n --show-non-errors\n\n## Configuration Options\n\n**Note:** This behavior described below is very different from versions prior to `0.6`.\n\nThe CLI uses the default options that come with JSHint. \n\nOnly one extra option is unique to node-jshint: `globals` \nallows you to define an object of globals that get ignored for every file.\nTo see an example you can look at how whitelisted globals are defined\nin the [jshint code](https://github.com/jshint/jshint/blob/c047ea1b01097fcc220fcd1a55c41f67ae2e6e81/jshint.js#L556)\n\nTo have your own configuration apply, there are several methods you can use:\n\n### Specify Manually\n\nSetting the `--config=/path/to/your/config` command line option to specify your own configuration file outside of the directory tree for your project.\n\n### Within your Project's Directory Tree\n\nWhen the CLI is called, and a configuration file isn't specified already, `node-jshint` will attempt to locate one for you starting in `pwd`. (or \"present working directory\") If this does not yield a `.jshintrc` file, it will move one level up (`..`) the directory tree all the way up to the filesystem root. If a file is found, it stops immediately and uses that set of configuration.\n\nThis setup allows you to set up **one** configuration file for your entire project. (place it in the root folder) As long as you run `jshint` from anywhere within your project directory tree, the same configuration file will be used.\n\n### Home Directory\n\nIf all the methods above do not yield a `.jshintrc` to use, the last place that will be checked is your user's `$HOME` directory.\n\n## File Extensions\n\nDefault extension for files is \".js\". If you want to use JSHint with other file extensions (.json), you need to pass this extra extension as an option :\n\n --extra-ext .json\n\n## Ignoring Files and Directories\n\nIf there is a .jshintignore file in your project's directory tree, (also provided you run `jshint` from within your project's directory) then any directories or files specified will be skipped over. (behaves just like a `.gitignore` file)\n\n**Note:** Pattern matching uses minimatch, with the nocase [option](https://github.com/isaacs/minimatch). When there is no match, it performs a left side match (when no forward slashes present and path is a directory).\n\n## Installing dependencies for development\n\n ./configure\n\n## Build Commands\n\n jake -T\n\n## Project Guidelines\n\n* All tests are passing.\n* No (new) JSHint errors are introduced.\n", + "readmeFilename": "README.md", + "_id": "jshint@0.9.1", + "_from": "jshint@~0.9.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.md similarity index 66% rename from node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.markdown rename to node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.md index 1635dee..3a27978 100755 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.markdown +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.md @@ -66,6 +66,38 @@ Core Team members: Maintainer: Anton Kovalyov +License +------- + +JSHint is licensed under the same slightly modified MIT license that JSLint is. +It stops evil-doers everywhere. + +JSHint is a derivative work of JSLint: + +Copyright (c) 2002 Douglas Crockford (www.JSLint.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 shall be used for Good, not Evil. + +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. + +JSHint was forked from the 2010-12-16 edition of JSLint. + Thank you! ---------- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/jshint.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/jshint.js index 5bf937c..53724f5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/jshint.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/jshint.js @@ -28,7 +28,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * - * JSHint was forked from 2010-12-16 edition of JSLint. + * JSHint was forked from the 2010-12-16 edition of JSLint. * */ @@ -55,8 +55,8 @@ JSHINT.errors is an array of objects containing these members: { - line : The line (relative to 0) at which the lint was found - character : The character (relative to 0) at which the lint was found + line : The line (relative to 1) at which the lint was found + character : The character (relative to 1) at which the lint was found reason : The problem evidence : The text line in which the problem occurred raw : The raw message before the details were inserted @@ -69,15 +69,6 @@ If a fatal error was found, a null will be the last element of the JSHINT.errors array. - You can request a Function Report, which shows all of the functions - and the parameters and vars that they use. This can be used to find - implied global variables and other problems. The report is in HTML and - can be inserted in an HTML . - - var myReport = JSHINT.report(limited); - - If limited is true, then the report will be limited to only errors. - You can request a data structure which contains JSHint's results. var myData = JSHINT.data(); @@ -96,7 +87,9 @@ functions: [ name: STRING, line: NUMBER, + character: NUMBER, last: NUMBER, + lastcharacter: NUMBER, param: [ STRING ], @@ -152,19 +145,20 @@ /*jshint evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true, - undef: true, maxlen: 100, indent:4 + undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true */ /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", - "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)", - "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", - "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", + "(breakage)", "(character)", "(context)", "(error)", "(explicitNewcap)", "(global)", + "(identifier)", "(last)", "(lastcharacter)", "(line)", "(loopage)", "(metrics)", + "(name)", "(onevar)", "(params)", "(scope)", "(statement)", "(verb)", "(tokens)", "(catch)", + "*", "+", "++", "-", "--", "\/", "<", "<=", "==", "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio, - Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, - CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, - Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag, - E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, + Autocompleter, Asset, Boolean, Builder, Buffer, Browser, Blob, COM, CScript, Canvas, + CustomAnimation, Class, Control, ComplexityCount, Chain, Color, Cookie, Core, DataView, Date, + Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMEvent, DOMReady, DOMParser, + Drag, E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey, HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement, @@ -181,49 +175,53 @@ HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement, - Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array, + Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array, Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, - MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native, - NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI, - POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError, - Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, + MAX_VALUE, MIN_VALUE, Map, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort, + MoveAnimation, MooTools, MutationObserver, NaN, Native, NEGATIVE_INFINITY, Node, NodeFilter, + Number, Object, ObjectRange, + Option, Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, + RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, Set, SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables, SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL, - VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, - XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a, - addEventListener, address, alert, apply, applicationCache, arguments, arity, - asi, b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, c, call, callee, - caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout, - close, closed, closure, comment, condition, confirm, console, constructor, - content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, - decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, - dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, - entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, - ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, + VBArray, WeakMap, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer, + XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, + "\\", a, abs, addEventListener, address, alert, apply, applicationCache, arguments, arity, + asi, atob, b, basic, basicToken, bitwise, blacklist, block, blur, boolOptions, boss, + browser, btoa, c, call, callee, caller, camelcase, cases, charAt, charCodeAt, character, + clearInterval, clearTimeout, close, closed, closure, comment, complexityCount, condition, + confirm, console, constructor, content, couch, create, css, curly, d, data, datalist, dd, debug, + decodeURI, decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, + dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, elem, + eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, forEach, forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions, g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict, hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include, - indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, + indent, indexOf, init, ins, internals, instanceOf, isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, iterator, java, join, jshint, - JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma, - latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, - log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, - moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen, - nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus, - onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param, - parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, - proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp, - readFile, readUrl, regexdash, removeEventListener, replace, report, require, - reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, - runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, - send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice, - smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow, - supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, - type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, - value, valueOf, var, version, WebSocket, white, window, Worker, wsh*/ + JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastcharacter, lastsemic, laxbreak, + laxcomma, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, + log, loopfunc, m, match, max, maxcomplexity, maxdepth, maxerr, maxlen, maxstatements, maxparams, + member, message, meta, module, moveBy, moveTo, mootools, multistr, name, navigator, new, newcap, + nestedBlockDepth, noarg, node, noempty, nomen, nonew, nonstandard, nud, onbeforeunload, onblur, + onerror, onevar, onecase, onfocus, onload, onresize, onunload, open, openDatabase, openURL, + opener, opera, options, outer, param, parent, parseFloat, parseInt, passfail, plusplus, + postMessage, pop, predef, print, process, prompt, proto, prototype, prototypejs, provides, push, + quit, quotmark, range, raw, reach, reason, regexp, readFile, readUrl, regexdash, + removeEventListener, replace, report, require, reserved, resizeBy, resizeTo, resolvePath, + resumeUpdates, respond, rhino, right, runCommand, scroll, scope, screen, scripturl, scrollBy, + scrollTo, scrollbar, search, seal, self, send, serialize, sessionStorage, setInterval, setTimeout, + setter, setterToken, shift, slice, smarttabs, sort, spawn, split, statement, statementCount, stack, + status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync, test, toLowerCase, + toString, toUpperCase, toint32, token, tokens, top, trailing, type, typeOf, Uint16Array, + Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, value, valueOf, var, vars, + version, verifyMaxParametersPerFunction, verifyMaxStatementsPerFunction, + verifyMaxComplexityPerFunction, verifyMaxNestedBlockDepthPerFunction, WebSocket, withstmt, white, + window, windows, Worker, worker, wsh, yui, YUI, Y, YUI_config*/ /*global exports: false */ @@ -239,19 +237,19 @@ var JSHINT = (function () { // These are operators that should not be used with the ! operator. bang = { - '<' : true, - '<=' : true, - '==' : true, - '===': true, - '!==': true, - '!=' : true, - '>' : true, - '>=' : true, - '+' : true, - '-' : true, - '*' : true, - '/' : true, - '%' : true + "<" : true, + "<=" : true, + "==" : true, + "===": true, + "!==": true, + "!=" : true, + ">" : true, + ">=" : true, + "+" : true, + "-" : true, + "*" : true, + "/" : true, + "%" : true }, // These are the JSHint boolean options. @@ -260,6 +258,7 @@ var JSHINT = (function () { bitwise : true, // if bitwise operators should not be allowed boss : true, // if advanced usage of assignments should be allowed browser : true, // if the standard browser globals should be predefined + camelcase : true, // if identifiers should be required in camel case couch : true, // if CouchDB globals should be predefined curly : true, // if curly braces around all blocks should be required debug : true, // if debugger statements should be allowed @@ -311,6 +310,7 @@ var JSHINT = (function () { regexp : true, // if the . should not be allowed in regexp literals rhino : true, // if the Rhino environment globals should be predefined undef : true, // if variables should be declared before used + unused : true, // if variables should be always used scripturl : true, // if script-targeted URLs should be tolerated shadow : true, // if variable shadowing should be tolerated smarttabs : true, // if smarttabs should be tolerated @@ -322,25 +322,73 @@ var JSHINT = (function () { trailing : true, // if trailing whitespace rules apply validthis : true, // if 'this' inside a non-constructor function is valid. // This is a function scoped option only. + withstmt : true, // if with statements should be allowed white : true, // if strict whitespace rules apply - wsh : true // if the Windows Scripting Host environment globals + worker : true, // if Web Worker script symbols should be allowed + wsh : true, // if the Windows Scripting Host environment globals // should be predefined + yui : true // YUI variables should be predefined + }, + + // These are the JSHint options that can take any value + // (we use this object to detect invalid options) + valOptions = { + maxlen : false, + indent : false, + maxerr : false, + predef : false, + quotmark : false, //'single'|'double'|true + scope : false, + maxstatements: false, // {int} max statements per function + maxdepth : false, // {int} max nested block depth per function + maxparams : false, // {int} max params per function + maxcomplexity: false // {int} max cyclomatic complexity per function + }, + + // These are JSHint boolean options which are shared with JSLint + // where the definition in JSHint is opposite JSLint + invertedOptions = { + bitwise : true, + forin : true, + newcap : true, + nomen : true, + plusplus : true, + regexp : true, + undef : true, + white : true, + + // Inverted and renamed, use JSHint name here + eqeqeq : true, + onevar : true }, + // These are JSHint boolean options which are shared with JSLint + // where the name has been changed but the effect is unchanged + renamedOptions = { + eqeq : "eqeqeq", + vars : "onevar", + windows : "wsh" + }, + + // browser contains a set of global names which are commonly provided by a // web browser environment. browser = { ArrayBuffer : false, ArrayBufferView : false, Audio : false, + Blob : false, addEventListener : false, applicationCache : false, + atob : false, blur : false, + btoa : false, clearInterval : false, clearTimeout : false, close : false, closed : false, DataView : false, + DOMParser : false, defaultStatus : false, document : false, event : false, @@ -413,9 +461,15 @@ var JSHINT = (function () { length : false, localStorage : false, location : false, + MessageChannel : false, + MessageEvent : false, + MessagePort : false, moveBy : false, moveTo : false, + MutationObserver : false, name : false, + Node : false, + NodeFilter : false, navigator : false, onbeforeunload : true, onblur : true, @@ -450,6 +504,7 @@ var JSHINT = (function () { window : false, Worker : false, XMLHttpRequest : false, + XMLSerializer : false, XPathEvaluator : false, XPathException : false, XPathExpression : false, @@ -472,6 +527,8 @@ var JSHINT = (function () { provides : false }, + declared, // Globals that were declared using /*global ... */ syntax. + devel = { alert : false, confirm : false, @@ -489,22 +546,11 @@ var JSHINT = (function () { "require" : false }, - escapes = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '/' : '\\/', - '\\': '\\\\' - }, - funct, // The current function functionicity = [ - 'closure', 'exception', 'global', 'label', - 'outer', 'unused', 'var' + "closure", "exception", "global", "label", + "outer", "unused", "var" ], functions, // All of the functions @@ -516,7 +562,7 @@ var JSHINT = (function () { jsonmode, jquery = { - '$' : false, + "$" : false, jQuery : false }, @@ -526,9 +572,9 @@ var JSHINT = (function () { membersOnly, mootools = { - '$' : false, - '$$' : false, - Assets : false, + "$" : false, + "$$" : false, + Asset : false, Browser : false, Chain : false, Class : false, @@ -537,6 +583,7 @@ var JSHINT = (function () { Core : false, Document : false, DomReady : false, + DOMEvent : false, DOMReady : false, Drag : false, Element : false, @@ -579,7 +626,7 @@ var JSHINT = (function () { __dirname : false, Buffer : false, console : false, - exports : false, + exports : true, // In Node it is ok to exports = module.exports = foo(); GLOBAL : false, global : false, module : false, @@ -598,15 +645,15 @@ var JSHINT = (function () { prevtoken, prototypejs = { - '$' : false, - '$$' : false, - '$A' : false, - '$F' : false, - '$H' : false, - '$R' : false, - '$break' : false, - '$continue' : false, - '$w' : false, + "$" : false, + "$$" : false, + "$A" : false, + "$F" : false, + "$H" : false, + "$R" : false, + "$break" : false, + "$continue" : false, + "$w" : false, Abstract : false, Ajax : false, Class : false, @@ -638,6 +685,8 @@ var JSHINT = (function () { Scriptaculous : false }, + quotmark, + rhino = { defineClass : false, deserialize : false, @@ -674,14 +723,16 @@ var JSHINT = (function () { encodeURI : false, encodeURIComponent : false, Error : false, - 'eval' : false, + "eval" : false, EvalError : false, Function : false, hasOwnProperty : false, isFinite : false, isNaN : false, JSON : false, + Map : false, Math : false, + NaN : false, Number : false, Object : false, parseInt : false, @@ -689,10 +740,12 @@ var JSHINT = (function () { RangeError : false, ReferenceError : false, RegExp : false, + Set : false, String : false, SyntaxError : false, TypeError : false, - URIError : false + URIError : false, + WeakMap : false }, // widely adopted global names that are not part of ECMAScript standard @@ -701,29 +754,21 @@ var JSHINT = (function () { unescape : false }, - standard_member = { - E : true, - LN2 : true, - LN10 : true, - LOG2E : true, - LOG10E : true, - MAX_VALUE : true, - MIN_VALUE : true, - NEGATIVE_INFINITY : true, - PI : true, - POSITIVE_INFINITY : true, - SQRT1_2 : true, - SQRT2 : true - }, - directive, syntax = {}, tab, token, + unuseds, urls, useESNextSyntax, warnings, + worker = { + importScripts : true, + postMessage : true, + self : true + }, + wsh = { ActiveXObject : true, Enumerator : true, @@ -736,8 +781,13 @@ var JSHINT = (function () { WSH : true, WScript : true, XDomainRequest : true - }; + }, + yui = { + YUI : false, + Y : false, + YUI_config : false + }; // Regular expressions. Some of these are stupidly long. var ax, cx, tx, nx, nxg, lx, ix, jx, ft; (function () { @@ -750,14 +800,14 @@ var JSHINT = (function () { cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; // token - tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/=(?!(\S*\/[gim]?))|\/(\*(jshint|jslint|members?|global)?|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; // characters in strings that need escapement nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // star slash - lx = /\*\/|\/\*/; + lx = /\*\//; // identifier ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; @@ -772,29 +822,85 @@ var JSHINT = (function () { function F() {} // Used by Object.create function is_own(object, name) { + // The object.hasOwnProperty method fails when the property under consideration + // is named 'hasOwnProperty'. So we have to use this more convoluted form. + return Object.prototype.hasOwnProperty.call(object, name); + } -// The object.hasOwnProperty method fails when the property under consideration -// is named 'hasOwnProperty'. So we have to use this more convoluted form. + function checkOption(name, t) { + if (valOptions[name] === undefined && boolOptions[name] === undefined) { + warning("Bad option: '" + name + "'.", t); + } + } - return Object.prototype.hasOwnProperty.call(object, name); + function isString(obj) { + return Object.prototype.toString.call(obj) === "[object String]"; } -// Provide critical ES5 functions to ES3. + // Provide critical ES5 functions to ES3. - if (typeof Array.isArray !== 'function') { + if (typeof Array.isArray !== "function") { Array.isArray = function (o) { - return Object.prototype.toString.apply(o) === '[object Array]'; + return Object.prototype.toString.apply(o) === "[object Array]"; + }; + } + + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fn, scope) { + var len = this.length; + + for (var i = 0; i < len; i++) { + fn.call(scope || this, this[i], i, this); + } + }; + } + + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + if (this === null || this === undefined) { + throw new TypeError(); + } + + var t = new Object(this); + var len = t.length >>> 0; + + if (len === 0) { + return -1; + } + + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n != n) { // shortcut for verifying if it's NaN + n = 0; + } else if (n !== 0 && n != Infinity && n != -Infinity) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + + if (n >= len) { + return -1; + } + + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + + return -1; }; } - if (typeof Object.create !== 'function') { + if (typeof Object.create !== "function") { Object.create = function (o) { F.prototype = o; return new F(); }; } - if (typeof Object.keys !== 'function') { + if (typeof Object.keys !== "function") { Object.keys = function (o) { var a = [], k; for (k in o) { @@ -806,74 +912,49 @@ var JSHINT = (function () { }; } -// Non standard methods - - if (typeof String.prototype.entityify !== 'function') { - String.prototype.entityify = function () { - return this - .replace(/&/g, '&') - .replace(//g, '>'); - }; - } - - if (typeof String.prototype.isAlpha !== 'function') { - String.prototype.isAlpha = function () { - return (this >= 'a' && this <= 'z\uffff') || - (this >= 'A' && this <= 'Z\uffff'); - }; - } + // Non standard methods - if (typeof String.prototype.isDigit !== 'function') { - String.prototype.isDigit = function () { - return (this >= '0' && this <= '9'); - }; + function isAlpha(str) { + return (str >= "a" && str <= "z\uffff") || + (str >= "A" && str <= "Z\uffff"); } - if (typeof String.prototype.supplant !== 'function') { - String.prototype.supplant = function (o) { - return this.replace(/\{([^{}]*)\}/g, function (a, b) { - var r = o[b]; - return typeof r === 'string' || typeof r === 'number' ? r : a; - }); - }; + function isDigit(str) { + return (str >= "0" && str <= "9"); } - if (typeof String.prototype.name !== 'function') { - String.prototype.name = function () { + function isIdentifier(token, value) { + if (!token) + return false; -// If the string looks like an identifier, then we can return it as is. -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can simply slap some quotes around it. -// Otherwise we must also replace the offending characters with safe -// sequences. + if (!token.identifier || token.value !== value) + return false; - if (ix.test(this)) { - return this; - } - if (nx.test(this)) { - return '"' + this.replace(nxg, function (a) { - var c = escapes[a]; - if (c) { - return c; - } - return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); - }) + '"'; - } - return '"' + this + '"'; - }; + return true; } + function supplant(str, data) { + return str.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = data[b]; + return typeof r === "string" || typeof r === "number" ? r : a; + }); + } function combine(t, o) { var n; for (n in o) { - if (is_own(o, n)) { + if (is_own(o, n) && !is_own(JSHINT.blacklist, n)) { t[n] = o[n]; } } } + function updatePredefined() { + Object.keys(JSHINT.blacklist).forEach(function (key) { + delete predefined[key]; + }); + } + function assume() { if (option.couch) { combine(predefined, couch); @@ -889,6 +970,7 @@ var JSHINT = (function () { if (option.node) { combine(predefined, node); + option.globalstrict = true; } if (option.devel) { @@ -915,6 +997,10 @@ var JSHINT = (function () { combine(predefined, mootools); } + if (option.worker) { + combine(predefined, worker); + } + if (option.wsh) { combine(predefined, wsh); } @@ -926,6 +1012,10 @@ var JSHINT = (function () { if (option.globalstrict && option.strict !== false) { option.strict = true; } + + if (option.yui) { + combine(predefined, yui); + } } @@ -934,7 +1024,7 @@ var JSHINT = (function () { var percentage = Math.floor((line / lines.length) * 100); throw { - name: 'JSHintError', + name: "JSHintError", line: line, character: chr, message: message + " (" + percentage + "% scanned).", @@ -949,26 +1039,27 @@ var JSHINT = (function () { function warning(m, t, a, b, c, d) { var ch, l, w; t = t || nexttoken; - if (t.id === '(end)') { // `~ + if (t.id === "(end)") { // `~ t = token; } l = t.line || 0; ch = t.from || 0; w = { - id: '(error)', + id: "(error)", raw: m, - evidence: lines[l - 1] || '', + evidence: lines[l - 1] || "", line: l, character: ch, + scope: JSHINT.scope, a: a, b: b, c: c, d: d }; - w.reason = m.supplant(w); + w.reason = supplant(m, w); JSHINT.errors.push(w); if (option.passfail) { - quit('Stopping. ', l, ch); + quit("Stopping. ", l, ch); } warnings += 1; if (warnings >= option.maxerr) { @@ -985,7 +1076,7 @@ var JSHINT = (function () { } function error(m, t, a, b, c, d) { - var w = warning(m, t, a, b, c, d); + warning(m, t, a, b, c, d); } function errorAt(m, l, ch, a, b, c, d) { @@ -995,6 +1086,17 @@ var JSHINT = (function () { }, a, b, c, d); } + // Tracking of "internal" scripts, like eval containing a static string + function addInternalSrc(elem, src) { + var i; + i = { + id: "(internal)", + elem: elem, + value: src + }; + JSHINT.internals.push(i); + return i; + } // lexical analysis and token construction @@ -1006,6 +1108,7 @@ var JSHINT = (function () { function nextLine() { var at, + match, tw; // trailing whitespace check if (line >= lines.length) @@ -1017,10 +1120,14 @@ var JSHINT = (function () { // If smarttabs option is used check for spaces followed by tabs only. // Otherwise check for any occurence of mixed tabs and spaces. - if (option.smarttabs) - at = s.search(/ \t/); - else - at = s.search(/ \t|\t /); + // Tabs and one space followed by block comment is allowed. + if (option.smarttabs) { + // negative look-behind for "//" + match = s.match(/(\/\/)? \t/); + at = match && !match[1] ? 0 : -1; + } else { + at = s.search(/ \t|\t [^\*]/); + } if (at >= 0) warningAt("Mixed spaces and tabs.", line, at + 1); @@ -1035,9 +1142,9 @@ var JSHINT = (function () { warningAt("Line too long.", line, s.length); // Check for trailing whitespaces - tw = /\s+$/.test(s); - if (option.trailing && tw && !/^\s+$/.test(s)) { - warningAt("Trailing whitespace.", line, tw); + tw = option.trailing && s.match(/^(.*?)\s+$/); + if (tw && !/^\s+$/.test(s)) { + warningAt("Trailing whitespace.", line, tw[1].length + 1); } return true; } @@ -1046,46 +1153,74 @@ var JSHINT = (function () { function it(type, value) { var i, t; - if (type === '(color)' || type === '(range)') { + + function checkName(name) { + if (!option.proto && name === "__proto__") { + warningAt("The '{a}' property is deprecated.", line, from, name); + return; + } + + if (!option.iterator && name === "__iterator__") { + warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name); + return; + } + + // Check for dangling underscores unless we're in Node + // environment and this identifier represents built-in + // Node globals with underscores. + + var hasDangling = /^(_+.*|.*_+)$/.test(name); + + if (option.nomen && hasDangling && name !== "_") { + if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name)) + return; + + warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name); + return; + } + + // Check for non-camelcase names. Names like MY_VAR and + // _myVar are okay though. + + if (option.camelcase) { + if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) { + warningAt("Identifier '{a}' is not in camel case.", line, from, value); + } + } + } + + if (type === "(color)" || type === "(range)") { t = {type: type}; - } else if (type === '(punctuator)' || - (type === '(identifier)' && is_own(syntax, value))) { - t = syntax[value] || syntax['(error)']; + } else if (type === "(punctuator)" || + (type === "(identifier)" && is_own(syntax, value))) { + t = syntax[value] || syntax["(error)"]; } else { t = syntax[type]; } + t = Object.create(t); - if (type === '(string)' || type === '(range)') { + + if (type === "(string)" || type === "(range)") { if (!option.scripturl && jx.test(value)) { warningAt("Script URL.", line, from); } } - if (type === '(identifier)') { + + if (type === "(identifier)") { t.identifier = true; - if (value === '__proto__' && !option.proto) { - warningAt("The '{a}' property is deprecated.", - line, from, value); - } else if (value === '__iterator__' && !option.iterator) { - warningAt("'{a}' is only available in JavaScript 1.7.", - line, from, value); - } else if (option.nomen && (value.charAt(0) === '_' || - value.charAt(value.length - 1) === '_')) { - if (!option.node || token.id === '.' || - (value !== '__dirname' && value !== '__filename')) { - warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value); - } - } + checkName(value); } + t.value = value; t.line = line; t.character = character; t.from = from; i = t.id; - if (i !== '(endline)') { + if (i !== "(endline)") { prereg = i && - (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || - i === 'return' || - i === 'case'); + (("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) || + i === "return" || + i === "case"); } return t; } @@ -1093,19 +1228,19 @@ var JSHINT = (function () { // Public lex methods return { init: function (source) { - if (typeof source === 'string') { + if (typeof source === "string") { lines = source - .replace(/\r\n/g, '\n') - .replace(/\r/g, '\n') - .split('\n'); + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .split("\n"); } else { lines = source; } // If the first line is a shebang (#!), make it a blank and move on. // Shebangs are used by Node scripts. - if (lines[0] && lines[0].substr(0, 2) === '#!') - lines[0] = ''; + if (lines[0] && lines[0].substr(0, 2) === "#!") + lines[0] = ""; line = 0; nextLine(); @@ -1113,7 +1248,7 @@ var JSHINT = (function () { }, range: function (begin, end) { - var c, value = ''; + var c, value = ""; from = character; if (s.charAt(0) !== begin) { errorAt("Expected '{a}' and instead saw '{b}'.", @@ -1124,14 +1259,14 @@ var JSHINT = (function () { character += 1; c = s.charAt(0); switch (c) { - case '': + case "": errorAt("Missing '{a}'.", line, character, c); break; case end: s = s.slice(1); character += 1; - return it('(range)', value); - case '\\': + return it("(range)", value); + case "\\": warningAt("Unexpected '{a}'.", line, character, c); } value += c; @@ -1142,10 +1277,11 @@ var JSHINT = (function () { // token -- this is called by advance to get the next token token: function () { - var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange; + var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n; function match(x) { var r = x.exec(s), r1; + if (r) { l = r[0].length; r1 = r[1]; @@ -1158,13 +1294,29 @@ var JSHINT = (function () { } function string(x) { - var c, j, r = '', allowNewLine = false; + var c, j, r = "", allowNewLine = false; - if (jsonmode && x !== '"') { + if (jsonmode && x !== "\"") { warningAt("Strings must use doublequote.", line, character); } + if (option.quotmark) { + if (option.quotmark === "single" && x !== "'") { + warningAt("Strings must use singlequote.", + line, character); + } else if (option.quotmark === "double" && x !== "\"") { + warningAt("Strings must use doublequote.", + line, character); + } else if (option.quotmark === true) { + quotmark = quotmark || x; + if (quotmark !== x) { + warningAt("Mixed double and single quotes.", + line, character); + } + } + } + function esc(n) { var i = parseInt(s.substr(j + 1, n), 16); j += n; @@ -1175,6 +1327,7 @@ var JSHINT = (function () { character += n; c = String.fromCharCode(i); } + j = 0; unclosedString: for (;;) { while (j >= s.length) { @@ -1192,63 +1345,77 @@ unclosedString: for (;;) { warningAt("Unclosed string.", cl, cf); } } + c = s.charAt(j); if (c === x) { character += 1; s = s.substr(j + 1); - return it('(string)', r, x); + return it("(string)", r, x); } - if (c < ' ') { - if (c === '\n' || c === '\r') { + + if (c < " ") { + if (c === "\n" || c === "\r") { break; } warningAt("Control character in string: {a}.", line, character + j, s.slice(0, j)); - } else if (c === '\\') { + } else if (c === "\\") { j += 1; character += 1; c = s.charAt(j); + n = s.charAt(j + 1); switch (c) { - case '\\': - case '"': - case '/': + case "\\": + case "\"": + case "/": break; - case '\'': + case "\'": if (jsonmode) { warningAt("Avoid \\'.", line, character); } break; - case 'b': - c = '\b'; + case "b": + c = "\b"; break; - case 'f': - c = '\f'; + case "f": + c = "\f"; break; - case 'n': - c = '\n'; + case "n": + c = "\n"; break; - case 'r': - c = '\r'; + case "r": + c = "\r"; break; - case 't': - c = '\t'; + case "t": + c = "\t"; break; - case 'u': + case "0": + c = "\0"; + // Octal literals fail in strict mode + // check if the number is between 00 and 07 + // where 'n' is the token next to 'c' + if (n >= 0 && n <= 7 && directive["use strict"]) { + warningAt( + "Octal literals are not allowed in strict mode.", + line, character); + } + break; + case "u": esc(4); break; - case 'v': + case "v": if (jsonmode) { warningAt("Avoid \\v.", line, character); } - c = '\v'; + c = "\v"; break; - case 'x': + case "x": if (jsonmode) { warningAt("Avoid \\x-.", line, character); } esc(2); break; - case '': + case "": // last character is escape character // always allow new line if escaped, but show // warning if option is not set @@ -1257,13 +1424,17 @@ unclosedString: for (;;) { if (jsonmode) { warningAt("Avoid EOL escapement.", line, character); } - c = ''; + c = ""; character -= 1; break; } warningAt("Bad escapement of EOL. Use option multistr if needed.", line, character); break; + case "!": + if (s.charAt(j - 2) === "<") + break; + /*falls through*/ default: warningAt("Bad escapement.", line, character); } @@ -1276,74 +1447,76 @@ unclosedString: for (;;) { for (;;) { if (!s) { - return it(nextLine() ? '(endline)' : '(end)', ''); + return it(nextLine() ? "(endline)" : "(end)", ""); } + t = match(tx); + if (!t) { - t = ''; - c = ''; - while (s && s < '!') { + t = ""; + c = ""; + while (s && s < "!") { s = s.substr(1); } if (s) { errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); - s = ''; + s = ""; } } else { // identifier - if (c.isAlpha() || c === '_' || c === '$') { - return it('(identifier)', t); + if (isAlpha(c) || c === "_" || c === "$") { + return it("(identifier)", t); } // number - if (c.isDigit()) { + if (isDigit(c)) { if (!isFinite(Number(t))) { warningAt("Bad number '{a}'.", line, character, t); } - if (s.substr(0, 1).isAlpha()) { + if (isAlpha(s.substr(0, 1))) { warningAt("Missing space after '{a}'.", line, character, t); } - if (c === '0') { + if (c === "0") { d = t.substr(1, 1); - if (d.isDigit()) { - if (token.id !== '.') { + if (isDigit(d)) { + if (token.id !== ".") { warningAt("Don't use extra leading zeros '{a}'.", line, character, t); } - } else if (jsonmode && (d === 'x' || d === 'X')) { + } else if (jsonmode && (d === "x" || d === "X")) { warningAt("Avoid 0x-. '{a}'.", line, character, t); } } - if (t.substr(t.length - 1) === '.') { + if (t.substr(t.length - 1) === ".") { warningAt( "A trailing decimal point can be confused with a dot '{a}'.", line, character, t); } - return it('(number)', t); + return it("(number)", t); } switch (t) { // string - case '"': + case "\"": case "'": return string(t); // // comment - case '//': - s = ''; + case "//": + s = ""; token.comment = true; break; // /* comment - case '/*': + case "/*": for (;;) { i = s.search(lx); if (i >= 0) { @@ -1353,38 +1526,35 @@ unclosedString: for (;;) { errorAt("Unclosed comment.", line, character); } } - character += i + 2; - if (s.substr(i, 1) === '/') { - errorAt("Nested comment.", line, character); - } s = s.substr(i + 2); token.comment = true; break; // /*members /*jshint /*global - case '/*members': - case '/*member': - case '/*jshint': - case '/*jslint': - case '/*global': - case '*/': + case "/*members": + case "/*member": + case "/*jshint": + case "/*jslint": + case "/*global": + case "*/": return { value: t, - type: 'special', + type: "special", line: line, character: character, from: from }; - case '': + case "": break; // / - case '/': - if (token.id === '/=') { + case "/": + if (s.charAt(0) === "=") { errorAt("A regular expression literal can be confused with '/='.", line, from); } + if (prereg) { depth = 0; captures = 0; @@ -1394,10 +1564,10 @@ unclosedString: for (;;) { c = s.charAt(l); l += 1; switch (c) { - case '': + case "": errorAt("Unclosed regular expression.", line, from); - return quit('Stopping.', line, from); - case '/': + return quit("Stopping.", line, from); + case "/": if (depth > 0) { warningAt("{a} unterminated regular expression " + "group(s).", line, from + l, depth); @@ -1415,55 +1585,55 @@ unclosedString: for (;;) { character += l; s = s.substr(l); q = s.charAt(0); - if (q === '/' || q === '*') { + if (q === "/" || q === "*") { errorAt("Confusing regular expression.", line, from); } - return it('(regexp)', c); - case '\\': + return it("(regexp)", c); + case "\\": c = s.charAt(l); - if (c < ' ') { + if (c < " ") { warningAt( "Unexpected control character in regular expression.", line, from + l); - } else if (c === '<') { + } else if (c === "<") { warningAt( "Unexpected escaped character '{a}' in regular expression.", line, from + l, c); } l += 1; break; - case '(': + case "(": depth += 1; b = false; - if (s.charAt(l) === '?') { + if (s.charAt(l) === "?") { l += 1; switch (s.charAt(l)) { - case ':': - case '=': - case '!': + case ":": + case "=": + case "!": l += 1; break; default: warningAt( -"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); +"Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l)); } } else { captures += 1; } break; - case '|': + case "|": b = false; break; - case ')': + case ")": if (depth === 0) { warningAt("Unescaped '{a}'.", - line, from + l, ')'); + line, from + l, ")"); } else { depth -= 1; } break; - case ' ': + case " ": q = 1; - while (s.charAt(l) === ' ') { + while (s.charAt(l) === " ") { l += 1; q += 1; } @@ -1472,19 +1642,16 @@ unclosedString: for (;;) { "Spaces are hard to count. Use {{a}}.", line, from + l, q); } break; - case '[': + case "[": c = s.charAt(l); - if (c === '^') { + if (c === "^") { l += 1; - if (option.regexp) { - warningAt("Insecure '{a}'.", - line, from + l, c); - } else if (s.charAt(l) === ']') { + if (s.charAt(l) === "]") { errorAt("Unescaped '{a}'.", - line, from + l, '^'); + line, from + l, "^"); } } - if (c === ']') { + if (c === "]") { warningAt("Empty class.", line, from + l - 1); } @@ -1494,8 +1661,8 @@ klass: do { c = s.charAt(l); l += 1; switch (c) { - case '[': - case '^': + case "[": + case "^": warningAt("Unescaped '{a}'.", line, from + l, c); if (isInRange) { @@ -1504,35 +1671,35 @@ klass: do { isLiteral = true; } break; - case '-': + case "-": if (isLiteral && !isInRange) { isLiteral = false; isInRange = true; } else if (isInRange) { isInRange = false; - } else if (s.charAt(l) === ']') { + } else if (s.charAt(l) === "]") { isInRange = true; } else { if (option.regexdash !== (l === 2 || (l === 3 && - s.charAt(1) === '^'))) { + s.charAt(1) === "^"))) { warningAt("Unescaped '{a}'.", - line, from + l - 1, '-'); + line, from + l - 1, "-"); } isLiteral = true; } break; - case ']': + case "]": if (isInRange && !option.regexdash) { warningAt("Unescaped '{a}'.", - line, from + l - 1, '-'); + line, from + l - 1, "-"); } break klass; - case '\\': + case "\\": c = s.charAt(l); - if (c < ' ') { + if (c < " ") { warningAt( "Unexpected control character in regular expression.", line, from + l); - } else if (c === '<') { + } else if (c === "<") { warningAt( "Unexpected escaped character '{a}' in regular expression.", line, from + l, c); } @@ -1542,7 +1709,7 @@ klass: do { if (/[wsd]/i.test(c)) { if (isInRange) { warningAt("Unescaped '{a}'.", - line, from + l, '-'); + line, from + l, "-"); isInRange = false; } isLiteral = false; @@ -1552,9 +1719,9 @@ klass: do { isLiteral = true; } break; - case '/': + case "/": warningAt("Unescaped '{a}'.", - line, from + l - 1, '/'); + line, from + l - 1, "/"); if (isInRange) { isInRange = false; @@ -1562,7 +1729,7 @@ klass: do { isLiteral = true; } break; - case '<': + case "<": if (isInRange) { isInRange = false; } else { @@ -1578,59 +1745,60 @@ klass: do { } } while (c); break; - case '.': + case ".": if (option.regexp) { warningAt("Insecure '{a}'.", line, from + l, c); } break; - case ']': - case '?': - case '{': - case '}': - case '+': - case '*': + case "]": + case "?": + case "{": + case "}": + case "+": + case "*": warningAt("Unescaped '{a}'.", line, from + l, c); } if (b) { switch (s.charAt(l)) { - case '?': - case '+': - case '*': + case "?": + case "+": + case "*": l += 1; - if (s.charAt(l) === '?') { + if (s.charAt(l) === "?") { l += 1; } break; - case '{': + case "{": l += 1; c = s.charAt(l); - if (c < '0' || c > '9') { + if (c < "0" || c > "9") { warningAt( "Expected a number and instead saw '{a}'.", line, from + l, c); + break; // No reason to continue checking numbers. } l += 1; low = +c; for (;;) { c = s.charAt(l); - if (c < '0' || c > '9') { + if (c < "0" || c > "9") { break; } l += 1; low = +c + (low * 10); } high = low; - if (c === ',') { + if (c === ",") { l += 1; high = Infinity; c = s.charAt(l); - if (c >= '0' && c <= '9') { + if (c >= "0" && c <= "9") { l += 1; high = +c; for (;;) { c = s.charAt(l); - if (c < '0' || c > '9') { + if (c < "0" || c > "9") { break; } l += 1; @@ -1638,13 +1806,13 @@ klass: do { } } } - if (s.charAt(l) !== '}') { + if (s.charAt(l) !== "}") { warningAt( -"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); +"Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c); } else { l += 1; } - if (s.charAt(l) === '?') { + if (s.charAt(l) === "?") { l += 1; } if (low > high) { @@ -1657,16 +1825,16 @@ klass: do { c = s.substr(0, l - 1); character += l; s = s.substr(l); - return it('(regexp)', c); + return it("(regexp)", c); } - return it('(punctuator)', t); + return it("(punctuator)", t); // punctuator - case '#': - return it('(punctuator)', t); + case "#": + return it("(punctuator)", t); default: - return it('(punctuator)', t); + return it("(punctuator)", t); } } } @@ -1675,25 +1843,38 @@ klass: do { }()); - function addlabel(t, type) { - - if (t === 'hasOwnProperty') { + function addlabel(t, type, token) { + if (t === "hasOwnProperty") { warning("'hasOwnProperty' is a really bad name."); } -// Define t in the current function in the current scope. - if (is_own(funct, t) && !funct['(global)']) { + // Define t in the current function in the current scope. + if (type === "exception") { + if (is_own(funct["(context)"], t)) { + if (funct[t] !== true && !option.node) { + warning("Value of '{a}' may be overwritten in IE.", nexttoken, t); + } + } + } + + if (is_own(funct, t) && !funct["(global)"]) { if (funct[t] === true) { if (option.latedef) warning("'{a}' was used before it was defined.", nexttoken, t); } else { - if (!option.shadow && type !== "exception") + if (!option.shadow && type !== "exception") { warning("'{a}' is already defined.", nexttoken, t); + } } } funct[t] = type; - if (funct['(global)']) { + + if (token) { + funct["(tokens)"][t] = token; + } + + if (funct["(global)"]) { global[t] = funct; if (is_own(implied, t)) { if (option.latedef) @@ -1707,102 +1888,161 @@ klass: do { function doOption() { - var b, obj, filter, o = nexttoken.value, t, v; + var nt = nexttoken; + var o = nt.value; + var quotmarkValue = option.quotmark; + var predef = {}; + var b, obj, filter, t, tn, v, minus; + switch (o) { - case '*/': + case "*/": error("Unbegun comment."); break; - case '/*members': - case '/*member': - o = '/*members'; + case "/*members": + case "/*member": + o = "/*members"; if (!membersOnly) { membersOnly = {}; } obj = membersOnly; + option.quotmark = false; break; - case '/*jshint': - case '/*jslint': + case "/*jshint": + case "/*jslint": obj = option; filter = boolOptions; break; - case '/*global': - obj = predefined; + case "/*global": + obj = predef; break; default: error("What?"); } + t = lex.token(); loop: for (;;) { + minus = false; for (;;) { - if (t.type === 'special' && t.value === '*/') { + if (t.type === "special" && t.value === "*/") { break loop; } - if (t.id !== '(endline)' && t.id !== ',') { + if (t.id !== "(endline)" && t.id !== ",") { break; } t = lex.token(); } - if (t.type !== '(string)' && t.type !== '(identifier)' && - o !== '/*members') { + + if (o === "/*global" && t.value === "-") { + minus = true; + t = lex.token(); + } + + if (t.type !== "(string)" && t.type !== "(identifier)" && o !== "/*members") { error("Bad option.", t); } + v = lex.token(); - if (v.id === ':') { + if (v.id === ":") { v = lex.token(); + if (obj === membersOnly) { - error("Expected '{a}' and instead saw '{b}'.", - t, '*/', ':'); + error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":"); } - if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.white = true; - obj.indent = b; - } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.maxerr = b; - } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) { + + if (o === "/*jshint") { + checkOption(t.value, t); + } + + var numericVals = [ + "maxstatements", + "maxparams", + "maxdepth", + "maxcomplexity", + "maxerr", + "maxlen", + "indent" + ]; + + if (numericVals.indexOf(t.value) > -1 && (o === "/*jshint" || o === "/*jslint")) { b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); + + if (typeof b !== "number" || !isFinite(b) || b <= 0 || Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", v, v.value); } - obj.maxlen = b; - } else if (t.value === 'validthis') { - if (funct['(global)']) { + + if (t.value === "indent") + obj.white = true; + + obj[t.value] = b; + } else if (t.value === "validthis") { + if (funct["(global)"]) { error("Option 'validthis' can't be used in a global scope."); } else { - if (v.value === 'true' || v.value === 'false') - obj[t.value] = v.value === 'true'; + if (v.value === "true" || v.value === "false") + obj[t.value] = v.value === "true"; else error("Bad option value.", v); } - } else if (v.value === 'true') { - obj[t.value] = true; - } else if (v.value === 'false') { - obj[t.value] = false; + } else if (t.value === "quotmark" && (o === "/*jshint")) { + switch (v.value) { + case "true": + obj.quotmark = true; + break; + case "false": + obj.quotmark = false; + break; + case "double": + case "single": + obj.quotmark = v.value; + break; + default: + error("Bad option value.", v); + } + } else if (v.value === "true" || v.value === "false") { + if (o === "/*jslint") { + tn = renamedOptions[t.value] || t.value; + obj[tn] = v.value === "true"; + if (invertedOptions[tn] !== undefined) { + obj[tn] = !obj[tn]; + } + } else { + obj[t.value] = v.value === "true"; + } + + if (t.value === "newcap") + obj["(explicitNewcap)"] = true; } else { error("Bad option value.", v); } t = lex.token(); } else { - if (o === '/*jshint' || o === '/*jslint') { + if (o === "/*jshint" || o === "/*jslint") { error("Missing option value.", t); } + obj[t.value] = false; + + if (o === "/*global" && minus === true) { + JSHINT.blacklist[t.value] = t.value; + updatePredefined(); + } + t = v; } } + + if (o === "/*members") { + option.quotmark = quotmarkValue; + } + + combine(predefined, predef); + + for (var key in predef) { + if (is_own(predef, key)) { + declared[key] = nt; + } + } + if (filter) { assume(); } @@ -1834,36 +2074,36 @@ loop: for (;;) { function advance(id, t) { switch (token.id) { - case '(number)': - if (nexttoken.id === '.') { + case "(number)": + if (nexttoken.id === ".") { warning("A dot following a number can be confused with a decimal point.", token); } break; - case '-': - if (nexttoken.id === '-' || nexttoken.id === '--') { + case "-": + if (nexttoken.id === "-" || nexttoken.id === "--") { warning("Confusing minusses."); } break; - case '+': - if (nexttoken.id === '+' || nexttoken.id === '++') { + case "+": + if (nexttoken.id === "+" || nexttoken.id === "++") { warning("Confusing plusses."); } break; } - if (token.type === '(string)' || token.identifier) { + if (token.type === "(string)" || token.identifier) { anonname = token.value; } if (id && nexttoken.id !== id) { if (t) { - if (nexttoken.id === '(end)') { + if (nexttoken.id === "(end)") { warning("Unmatched '{a}'.", t, t.id); } else { warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", nexttoken, id, t.id, t.line, nexttoken.value); } - } else if (nexttoken.type !== '(identifier)' || + } else if (nexttoken.type !== "(identifier)" || nexttoken.value !== id) { warning("Expected '{a}' and instead saw '{b}'.", nexttoken, id, nexttoken.value); @@ -1874,13 +2114,13 @@ loop: for (;;) { token = nexttoken; for (;;) { nexttoken = lookahead.shift() || lex.token(); - if (nexttoken.id === '(end)' || nexttoken.id === '(error)') { + if (nexttoken.id === "(end)" || nexttoken.id === "(error)") { return; } - if (nexttoken.type === 'special') { + if (nexttoken.type === "special") { doOption(); } else { - if (nexttoken.id !== '(endline)') { + if (nexttoken.id !== "(endline)") { break; } } @@ -1903,15 +2143,15 @@ loop: for (;;) { // They are elements of the parsing method called Top Down Operator Precedence. function expression(rbp, initial) { - var left, isArray = false; + var left, isArray = false, isObject = false; - if (nexttoken.id === '(end)') + if (nexttoken.id === "(end)") error("Unexpected early end of program.", token); advance(); if (initial) { - anonname = 'anonymous'; - funct['(verb)'] = token.value; + anonname = "anonymous"; + funct["(verb)"] = token.value; } if (initial === true && token.fud) { left = token.fud(); @@ -1919,7 +2159,7 @@ loop: for (;;) { if (token.nud) { left = token.nud(); } else { - if (nexttoken.type === '(number)' && token.id === '.') { + if (nexttoken.type === "(number)" && token.id === ".") { warning("A leading decimal point can be confused with a dot: '.{a}'.", token, nexttoken.value); advance(); @@ -1930,10 +2170,32 @@ loop: for (;;) { } } while (rbp < nexttoken.lbp) { - isArray = token.value === 'Array'; + isArray = token.value === "Array"; + isObject = token.value === "Object"; + + // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object() + // Line breaks in IfStatement heads exist to satisfy the checkJSHint + // "Line too long." error. + if (left && (left.value || (left.first && left.first.value))) { + // If the left.value is not "new", or the left.first.value is a "." + // then safely assume that this is not "new Array()" and possibly + // not "new Object()"... + if (left.value !== "new" || + (left.first && left.first.value && left.first.value === ".")) { + isArray = false; + // ...In the case of Object, if the left.value and token.value + // are not equal, then safely assume that this not "new Object()" + if (left.value !== token.value) { + isObject = false; + } + } + } + advance(); - if (isArray && token.id === '(' && nexttoken.id === ')') + if (isArray && token.id === "(" && nexttoken.id === ")") warning("Use the array literal notation [].", token); + if (isObject && token.id === "(" && nexttoken.id === ")") + warning("Use the object literal notation {}.", token); if (token.led) { left = token.led(left); } else { @@ -1981,6 +2243,9 @@ loop: for (;;) { if (option.white) { left = left || token; right = right || nexttoken; + if (left.value === ";" && right.value === ";") { + return; + } if (left.line === right.line && left.character === right.from) { left.from += (left.character - left.from); warning("Missing space after '{a}'.", @@ -2007,7 +2272,7 @@ loop: for (;;) { function indentation(bias) { var i; - if (option.white && nexttoken.id !== '(end)') { + if (option.white && nexttoken.id !== "(end)") { i = indent + (bias || 0); if (nexttoken.from !== i) { warning( @@ -2038,19 +2303,17 @@ loop: for (;;) { token.from += (token.character - token.from); warning("Unexpected space after '{a}'.", token, token.value); } - advance(','); + advance(","); nonadjacent(token, nexttoken); } - comma.first = true; - // Functional constructors for making the symbols that will be inherited by // tokens. function symbol(s, p) { var x = syntax[s]; - if (!x || typeof x !== 'object') { + if (!x || typeof x !== "object") { syntax[s] = x = { id: s, lbp: p, @@ -2083,7 +2346,7 @@ loop: for (;;) { function reserveName(x) { var c = x.id.charAt(0); - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) { x.identifier = x.reserved = true; } return x; @@ -2093,14 +2356,14 @@ loop: for (;;) { function prefix(s, f) { var x = symbol(s, 150); reserveName(x); - x.nud = (typeof f === 'function') ? f : function () { + x.nud = (typeof f === "function") ? f : function () { this.right = expression(150); - this.arity = 'unary'; - if (this.id === '++' || this.id === '--') { + this.arity = "unary"; + if (this.id === "++" || this.id === "--") { if (option.plusplus) { warning("Unexpected use of '{a}'.", this, this.id); } else if ((!this.right.identifier || this.right.reserved) && - this.right.id !== '.' && this.right.id !== '[') { + this.right.id !== "." && this.right.id !== "[") { warning("Bad operand.", this); } } @@ -2127,7 +2390,7 @@ loop: for (;;) { function reservevar(s, v) { return reserve(s, function () { - if (typeof v === 'function') { + if (typeof v === "function") { v(this); } return this; @@ -2144,9 +2407,9 @@ loop: for (;;) { nonadjacent(token, nexttoken); } if (s === "in" && left.id === "!") { - warning("Confusing use of '{a}'.", left, '!'); + warning("Confusing use of '{a}'.", left, "!"); } - if (typeof f === 'function') { + if (typeof f === "function") { return f(left, this); } else { this.left = left; @@ -2164,16 +2427,17 @@ loop: for (;;) { nobreaknonadjacent(prevtoken, token); nonadjacent(token, nexttoken); var right = expression(100); - if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { + + if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) { warning("Use the isNaN function to compare with NaN.", this); } else if (f) { f.apply(this, [left, right]); } - if (left.id === '!') { - warning("Confusing use of '{a}'.", left, '!'); + if (left.id === "!") { + warning("Confusing use of '{a}'.", left, "!"); } - if (right.id === '!') { - warning("Confusing use of '{a}'.", right, '!'); + if (right.id === "!") { + warning("Confusing use of '{a}'.", right, "!"); } this.left = left; this.right = right; @@ -2185,49 +2449,54 @@ loop: for (;;) { function isPoorRelation(node) { return node && - ((node.type === '(number)' && +node.value === 0) || - (node.type === '(string)' && node.value === '') || - (node.type === 'null' && !option.eqnull) || - node.type === 'true' || - node.type === 'false' || - node.type === 'undefined'); + ((node.type === "(number)" && +node.value === 0) || + (node.type === "(string)" && node.value === "") || + (node.type === "null" && !option.eqnull) || + node.type === "true" || + node.type === "false" || + node.type === "undefined"); } - function assignop(s, f) { + function assignop(s) { symbol(s, 20).exps = true; + return infix(s, function (left, that) { - var l; that.left = left; + if (predefined[left.value] === false && - scope[left.value]['(global)'] === true) { + scope[left.value]["(global)"] === true) { warning("Read only.", left); - } else if (left['function']) { + } else if (left["function"]) { warning("'{a}' is a function.", left, left.value); } + if (left) { - if (option.esnext && funct[left.value] === 'const') { + if (option.esnext && funct[left.value] === "const") { warning("Attempting to override '{a}' which is a constant", left, left.value); } - if (left.id === '.' || left.id === '[') { - if (!left.left || left.left.value === 'arguments') { - warning('Bad assignment.', that); + + if (left.id === "." || left.id === "[") { + if (!left.left || left.left.value === "arguments") { + warning("Bad assignment.", that); } that.right = expression(19); return that; } else if (left.identifier && !left.reserved) { - if (funct[left.value] === 'exception') { + if (funct[left.value] === "exception") { warning("Do not assign to the exception parameter.", left); } that.right = expression(19); return that; } - if (left === syntax['function']) { + + if (left === syntax["function"]) { warning( "Expected an identifier in an assignment and instead saw a function invocation.", token); } } + error("Bad assignment.", that); }, 20); } @@ -2236,7 +2505,7 @@ loop: for (;;) { function bitwise(s, f, p) { var x = symbol(s, p); reserveName(x); - x.led = (typeof f === 'function') ? f : function (left) { + x.led = (typeof f === "function") ? f : function (left) { if (option.bitwise) { warning("Unexpected use of '{a}'.", this, this.id); } @@ -2257,12 +2526,12 @@ loop: for (;;) { nonadjacent(prevtoken, token); nonadjacent(token, nexttoken); if (left) { - if (left.id === '.' || left.id === '[' || + if (left.id === "." || left.id === "[" || (left.identifier && !left.reserved)) { expression(19); return that; } - if (left === syntax['function']) { + if (left === syntax["function"]) { warning( "Expected an identifier in an assignment, and instead saw a function invocation.", token); @@ -2274,13 +2543,13 @@ loop: for (;;) { } - function suffix(s, f) { + function suffix(s) { var x = symbol(s, 150); x.led = function (left) { if (option.plusplus) { warning("Unexpected use of '{a}'.", this, this.id); } else if ((!left.identifier || left.reserved) && - left.id !== '.' && left.id !== '[') { + left.id !== "." && left.id !== "[") { warning("Bad operand.", this); } this.left = left; @@ -2299,7 +2568,7 @@ loop: for (;;) { // `undefined` as a function param is a common pattern to protect // against the case when somebody does `undefined = true` and // help with minification. More info: https://gist.github.com/315916 - if (!fnparam || token.value !== 'undefined') { + if (!fnparam || token.value !== "undefined") { warning("Expected an identifier and instead saw '{a}' (a reserved word).", token, token.id); } @@ -2315,7 +2584,7 @@ loop: for (;;) { if (i) { return i; } - if (token.id === 'function' && nexttoken.id === '(') { + if (token.id === "function" && nexttoken.id === "(") { warning("Missing name in function declaration."); } else { error("Expected an identifier and instead saw '{a}'.", @@ -2326,7 +2595,7 @@ loop: for (;;) { function reachable(s) { var i = 0, t; - if (nexttoken.id !== ';' || noreach) { + if (nexttoken.id !== ";" || noreach) { return; } for (;;) { @@ -2334,8 +2603,8 @@ loop: for (;;) { if (t.reach) { return; } - if (t.id !== '(endline)') { - if (t.id === 'function') { + if (t.id !== "(endline)") { + if (t.id === "function") { if (!option.latedef) { break; } @@ -2359,26 +2628,34 @@ loop: for (;;) { return; } -// Is this a labelled statement? + // Is this a labelled statement? - if (t.identifier && !t.reserved && peek().id === ':') { + if (t.identifier && !t.reserved && peek().id === ":") { advance(); - advance(':'); + advance(":"); scope = Object.create(s); - addlabel(t.value, 'label'); - if (!nexttoken.labelled) { - warning("Label '{a}' on {b} statement.", - nexttoken, t.value, nexttoken.value); + addlabel(t.value, "label"); + + if (!nexttoken.labelled && nexttoken.value !== "{") { + warning("Label '{a}' on {b} statement.", nexttoken, t.value, nexttoken.value); } - if (jx.test(t.value + ':')) { - warning("Label '{a}' looks like a javascript url.", - t, t.value); + + if (jx.test(t.value + ":")) { + warning("Label '{a}' looks like a javascript url.", t, t.value); } + nexttoken.label = t.value; t = nexttoken; } -// Parse the statement. + // Is it a lonely block? + + if (t.id === "{") { + block(true, true); + return; + } + + // Parse the statement. if (!noindent) { indentation(); @@ -2386,27 +2663,32 @@ loop: for (;;) { r = expression(0, true); // Look for the final semicolon. + if (!t.block) { if (!option.expr && (!r || !r.exps)) { warning("Expected an assignment or function call and instead saw an expression.", token); - } else if (option.nonew && r.id === '(' && r.left.id === 'new') { - warning("Do not use 'new' for side effects."); + } else if (option.nonew && r.id === "(" && r.left.id === "new") { + warning("Do not use 'new' for side effects.", t); + } + + if (nexttoken.id === ",") { + return comma(); } - if (nexttoken.id !== ';') { + if (nexttoken.id !== ";") { if (!option.asi) { // If this is the last statement in a block that ends on // the same line *and* option lastsemic is on, ignore the warning. // Otherwise, complain about missing semicolon. - if (!option.lastsemic || nexttoken.id !== '}' || + if (!option.lastsemic || nexttoken.id !== "}" || nexttoken.line !== token.line) { warningAt("Missing semicolon.", token.line, token.character); } } } else { adjacent(token, nexttoken); - advance(';'); + advance(";"); nonadjacent(token, nexttoken); } } @@ -2420,15 +2702,15 @@ loop: for (;;) { function statements(startLine) { - var a = [], f, p; + var a = [], p; - while (!nexttoken.reach && nexttoken.id !== '(end)') { - if (nexttoken.id === ';') { + while (!nexttoken.reach && nexttoken.id !== "(end)") { + if (nexttoken.id === ";") { p = peek(); if (!p || p.id !== "(") { warning("Unnecessary semicolon."); } - advance(';'); + advance(";"); } else { a.push(statement(startLine === nexttoken.line)); } @@ -2479,7 +2761,8 @@ loop: for (;;) { } if (token.value === "use strict") { - option.newcap = true; + if (!option["(explicitNewcap)"]) + option.newcap = true; option.undef = true; } @@ -2515,14 +2798,21 @@ loop: for (;;) { d; inblock = ordinary; - if (!ordinary || !option.funcscope) scope = Object.create(scope); + + if (!ordinary || !option.funcscope) + scope = Object.create(scope); + nonadjacent(token, nexttoken); t = nexttoken; - if (nexttoken.id === '{') { - advance('{'); + var metrics = funct["(metrics)"]; + metrics.nestedBlockDepth += 1; + metrics.verifyMaxNestedBlockDepthPerFunction(); + + if (nexttoken.id === "{") { + advance("{"); line = token.line; - if (nexttoken.id !== '}') { + if (nexttoken.id !== "}") { indent += option.indent; while (!ordinary && nexttoken.from > indent) { indent += option.indent; @@ -2537,7 +2827,7 @@ loop: for (;;) { } directives(); - if (option.strict && funct['(context)']['(global)']) { + if (option.strict && funct["(context)"]["(global)"]) { if (!m["use strict"] && !directive["use strict"]) { warning("Missing \"use strict\" statement."); } @@ -2546,6 +2836,8 @@ loop: for (;;) { a = statements(line); + metrics.statementCount += a.length; + if (isfunc) { directive = m; } @@ -2557,15 +2849,15 @@ loop: for (;;) { } else if (line !== nexttoken.line) { indentation(); } - advance('}', t); + advance("}", t); indent = old_indent; } else if (!ordinary) { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); + nexttoken, "{", nexttoken.value); } else { if (!stmt || option.curly) warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); + nexttoken, "{", nexttoken.value); noreach = true; indent += option.indent; @@ -2574,21 +2866,22 @@ loop: for (;;) { indent -= option.indent; noreach = false; } - funct['(verb)'] = null; + funct["(verb)"] = null; if (!ordinary || !option.funcscope) scope = s; inblock = b; if (ordinary && option.noempty && (!a || a.length === 0)) { warning("Empty block."); } + metrics.nestedBlockDepth -= 1; return a; } function countMember(m) { - if (membersOnly && typeof membersOnly[m] !== 'boolean') { + if (membersOnly && typeof membersOnly[m] !== "boolean") { warning("Unexpected /*member '{a}'.", token, m); } - if (typeof member[m] === 'number') { + if (typeof member[m] === "number") { member[m] += 1; } else { member[m] = 1; @@ -2598,7 +2891,7 @@ loop: for (;;) { function note_implied(token) { var name = token.value, line = token.line, a = implied[name]; - if (typeof a === 'function') { + if (typeof a === "function") { a = false; } @@ -2613,16 +2906,16 @@ loop: for (;;) { // Build the syntax table by declaring the syntactic elements of the language. - type('(number)', function () { + type("(number)", function () { return this; }); - type('(string)', function () { + type("(string)", function () { return this; }); - syntax['(identifier)'] = { - type: '(identifier)', + syntax["(identifier)"] = { + type: "(identifier)", lbp: 0, identifier: true, nud: function () { @@ -2630,13 +2923,13 @@ loop: for (;;) { s = scope[v], f; - if (typeof s === 'function') { + if (typeof s === "function") { // Protection against accidental inheritance. s = undefined; - } else if (typeof s === 'boolean') { + } else if (typeof s === "boolean") { f = funct; funct = functions[0]; - addlabel(v, 'var'); + addlabel(v, "var"); s = funct; funct = f; } @@ -2645,21 +2938,21 @@ loop: for (;;) { if (funct === s) { // Change 'unused' to 'var', and reject labels. switch (funct[v]) { - case 'unused': - funct[v] = 'var'; + case "unused": + funct[v] = "var"; break; - case 'unction': - funct[v] = 'function'; - this['function'] = true; + case "unction": + funct[v] = "function"; + this["function"] = true; break; - case 'function': - this['function'] = true; + case "function": + this["function"] = true; break; - case 'label': + case "label": warning("'{a}' is a statement label.", token, v); break; } - } else if (funct['(global)']) { + } else if (funct["(global)"]) { // The name is not defined in the function. If we are in the global // scope, then we have an undefined variable. // @@ -2667,32 +2960,33 @@ loop: for (;;) { // the base object of a reference is null so no need to display warning // if we're inside of typeof or delete. - if (option.undef && typeof predefined[v] !== 'boolean') { + if (option.undef && typeof predefined[v] !== "boolean") { // Attempting to subscript a null reference will throw an // error, even within the typeof and delete operators - if (!(anonname === 'typeof' || anonname === 'delete') || - (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) { + if (!(anonname === "typeof" || anonname === "delete") || + (nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) { isundef(funct, "'{a}' is not defined.", token, v); } } + note_implied(token); } else { // If the name is already defined in the current // function, but not as outer, then there is a scope error. switch (funct[v]) { - case 'closure': - case 'function': - case 'var': - case 'unused': + case "closure": + case "function": + case "var": + case "unused": warning("'{a}' used out of scope.", token, v); break; - case 'label': + case "label": warning("'{a}' is a statement label.", token, v); break; - case 'outer': - case 'global': + case "outer": + case "global": break; default: // If the name is defined in an outer function, make an outer entry, @@ -2702,16 +2996,16 @@ loop: for (;;) { } else if (s === null) { warning("'{a}' is not allowed.", token, v); note_implied(token); - } else if (typeof s !== 'object') { + } else if (typeof s !== "object") { // Operators typeof and delete do not raise runtime errors even // if the base object of a reference is null so no need to // display warning if we're inside of typeof or delete. if (option.undef) { // Attempting to subscript a null reference will throw an // error, even within the typeof and delete operators - if (!(anonname === 'typeof' || anonname === 'delete') || + if (!(anonname === "typeof" || anonname === "delete") || (nexttoken && - (nexttoken.value === '.' || nexttoken.value === '['))) { + (nexttoken.value === "." || nexttoken.value === "["))) { isundef(funct, "'{a}' is not defined.", token, v); } @@ -2720,22 +3014,21 @@ loop: for (;;) { note_implied(token); } else { switch (s[v]) { - case 'function': - case 'unction': - this['function'] = true; - s[v] = 'closure'; - funct[v] = s['(global)'] ? 'global' : 'outer'; + case "function": + case "unction": + this["function"] = true; + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; break; - case 'var': - case 'unused': - s[v] = 'closure'; - funct[v] = s['(global)'] ? 'global' : 'outer'; + case "var": + case "unused": + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; break; - case 'closure': - case 'parameter': - funct[v] = s['(global)'] ? 'global' : 'outer'; + case "closure": + funct[v] = s["(global)"] ? "global" : "outer"; break; - case 'label': + case "label": warning("'{a}' is a statement label.", token, v); } } @@ -2749,123 +3042,122 @@ loop: for (;;) { } }; - type('(regexp)', function () { + type("(regexp)", function () { return this; }); // ECMAScript parser - delim('(endline)'); - delim('(begin)'); - delim('(end)').reach = true; - delim(''); - delim('(error)').reach = true; - delim('}').reach = true; - delim(')'); - delim(']'); - delim('"').reach = true; + delim("(endline)"); + delim("(begin)"); + delim("(end)").reach = true; + delim(""); + delim("(error)").reach = true; + delim("}").reach = true; + delim(")"); + delim("]"); + delim("\"").reach = true; delim("'").reach = true; - delim(';'); - delim(':').reach = true; - delim(','); - delim('#'); - delim('@'); - reserve('else'); - reserve('case').reach = true; - reserve('catch'); - reserve('default').reach = true; - reserve('finally'); - reservevar('arguments', function (x) { - if (directive['use strict'] && funct['(global)']) { + delim(";"); + delim(":").reach = true; + delim(","); + delim("#"); + delim("@"); + reserve("else"); + reserve("case").reach = true; + reserve("catch"); + reserve("default").reach = true; + reserve("finally"); + reservevar("arguments", function (x) { + if (directive["use strict"] && funct["(global)"]) { warning("Strict violation.", x); } }); - reservevar('eval'); - reservevar('false'); - reservevar('Infinity'); - reservevar('NaN'); - reservevar('null'); - reservevar('this', function (x) { - if (directive['use strict'] && !option.validthis && ((funct['(statement)'] && - funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) { + reservevar("eval"); + reservevar("false"); + reservevar("Infinity"); + reservevar("null"); + reservevar("this", function (x) { + if (directive["use strict"] && !option.validthis && ((funct["(statement)"] && + funct["(name)"].charAt(0) > "Z") || funct["(global)"])) { warning("Possible strict violation.", x); } }); - reservevar('true'); - reservevar('undefined'); - assignop('=', 'assign', 20); - assignop('+=', 'assignadd', 20); - assignop('-=', 'assignsub', 20); - assignop('*=', 'assignmult', 20); - assignop('/=', 'assigndiv', 20).nud = function () { + reservevar("true"); + reservevar("undefined"); + assignop("=", "assign", 20); + assignop("+=", "assignadd", 20); + assignop("-=", "assignsub", 20); + assignop("*=", "assignmult", 20); + assignop("/=", "assigndiv", 20).nud = function () { error("A regular expression literal can be confused with '/='."); }; - assignop('%=', 'assignmod', 20); - bitwiseassignop('&=', 'assignbitand', 20); - bitwiseassignop('|=', 'assignbitor', 20); - bitwiseassignop('^=', 'assignbitxor', 20); - bitwiseassignop('<<=', 'assignshiftleft', 20); - bitwiseassignop('>>=', 'assignshiftright', 20); - bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); - infix('?', function (left, that) { + assignop("%=", "assignmod", 20); + bitwiseassignop("&=", "assignbitand", 20); + bitwiseassignop("|=", "assignbitor", 20); + bitwiseassignop("^=", "assignbitxor", 20); + bitwiseassignop("<<=", "assignshiftleft", 20); + bitwiseassignop(">>=", "assignshiftright", 20); + bitwiseassignop(">>>=", "assignshiftrightunsigned", 20); + infix("?", function (left, that) { that.left = left; that.right = expression(10); - advance(':'); - that['else'] = expression(10); + advance(":"); + that["else"] = expression(10); return that; }, 30); - infix('||', 'or', 40); - infix('&&', 'and', 50); - bitwise('|', 'bitor', 70); - bitwise('^', 'bitxor', 80); - bitwise('&', 'bitand', 90); - relation('==', function (left, right) { - var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null'); + infix("||", "or", 40); + infix("&&", "and", 50); + bitwise("|", "bitor", 70); + bitwise("^", "bitxor", 80); + bitwise("&", "bitand", 90); + relation("==", function (left, right) { + var eqnull = option.eqnull && (left.value === "null" || right.value === "null"); if (!eqnull && option.eqeqeq) - warning("Expected '{a}' and instead saw '{b}'.", this, '===', '=='); + warning("Expected '{a}' and instead saw '{b}'.", this, "===", "=="); else if (isPoorRelation(left)) - warning("Use '{a}' to compare with '{b}'.", this, '===', left.value); + warning("Use '{a}' to compare with '{b}'.", this, "===", left.value); else if (isPoorRelation(right)) - warning("Use '{a}' to compare with '{b}'.", this, '===', right.value); + warning("Use '{a}' to compare with '{b}'.", this, "===", right.value); return this; }); - relation('==='); - relation('!=', function (left, right) { + relation("==="); + relation("!=", function (left, right) { var eqnull = option.eqnull && - (left.value === 'null' || right.value === 'null'); + (left.value === "null" || right.value === "null"); if (!eqnull && option.eqeqeq) { warning("Expected '{a}' and instead saw '{b}'.", - this, '!==', '!='); + this, "!==", "!="); } else if (isPoorRelation(left)) { warning("Use '{a}' to compare with '{b}'.", - this, '!==', left.value); + this, "!==", left.value); } else if (isPoorRelation(right)) { warning("Use '{a}' to compare with '{b}'.", - this, '!==', right.value); + this, "!==", right.value); } return this; }); - relation('!=='); - relation('<'); - relation('>'); - relation('<='); - relation('>='); - bitwise('<<', 'shiftleft', 120); - bitwise('>>', 'shiftright', 120); - bitwise('>>>', 'shiftrightunsigned', 120); - infix('in', 'in', 120); - infix('instanceof', 'instanceof', 120); - infix('+', function (left, that) { + relation("!=="); + relation("<"); + relation(">"); + relation("<="); + relation(">="); + bitwise("<<", "shiftleft", 120); + bitwise(">>", "shiftright", 120); + bitwise(">>>", "shiftrightunsigned", 120); + infix("in", "in", 120); + infix("instanceof", "instanceof", 120); + infix("+", function (left, that) { var right = expression(130); - if (left && right && left.id === '(string)' && right.id === '(string)') { + if (left && right && left.id === "(string)" && right.id === "(string)") { left.value += right.value; left.character = right.character; if (!option.scripturl && jx.test(left.value)) { @@ -2877,105 +3169,102 @@ loop: for (;;) { that.right = right; return that; }, 130); - prefix('+', 'num'); - prefix('+++', function () { + prefix("+", "num"); + prefix("+++", function () { warning("Confusing pluses."); this.right = expression(150); - this.arity = 'unary'; + this.arity = "unary"; return this; }); - infix('+++', function (left) { + infix("+++", function (left) { warning("Confusing pluses."); this.left = left; this.right = expression(130); return this; }, 130); - infix('-', 'sub', 130); - prefix('-', 'neg'); - prefix('---', function () { + infix("-", "sub", 130); + prefix("-", "neg"); + prefix("---", function () { warning("Confusing minuses."); this.right = expression(150); - this.arity = 'unary'; + this.arity = "unary"; return this; }); - infix('---', function (left) { + infix("---", function (left) { warning("Confusing minuses."); this.left = left; this.right = expression(130); return this; }, 130); - infix('*', 'mult', 140); - infix('/', 'div', 140); - infix('%', 'mod', 140); - - suffix('++', 'postinc'); - prefix('++', 'preinc'); - syntax['++'].exps = true; - - suffix('--', 'postdec'); - prefix('--', 'predec'); - syntax['--'].exps = true; - prefix('delete', function () { + infix("*", "mult", 140); + infix("/", "div", 140); + infix("%", "mod", 140); + + suffix("++", "postinc"); + prefix("++", "preinc"); + syntax["++"].exps = true; + + suffix("--", "postdec"); + prefix("--", "predec"); + syntax["--"].exps = true; + prefix("delete", function () { var p = expression(0); - if (!p || (p.id !== '.' && p.id !== '[')) { + if (!p || (p.id !== "." && p.id !== "[")) { warning("Variables should not be deleted."); } this.first = p; return this; }).exps = true; - prefix('~', function () { + prefix("~", function () { if (option.bitwise) { - warning("Unexpected '{a}'.", this, '~'); + warning("Unexpected '{a}'.", this, "~"); } expression(150); return this; }); - prefix('!', function () { + prefix("!", function () { this.right = expression(150); - this.arity = 'unary'; + this.arity = "unary"; if (bang[this.right.id] === true) { - warning("Confusing use of '{a}'.", this, '!'); + warning("Confusing use of '{a}'.", this, "!"); } return this; }); - prefix('typeof', 'typeof'); - prefix('new', function () { + prefix("typeof", "typeof"); + prefix("new", function () { var c = expression(155), i; - if (c && c.id !== 'function') { + if (c && c.id !== "function") { if (c.identifier) { - c['new'] = true; + c["new"] = true; switch (c.value) { - case 'Object': - warning("Use the object literal notation {}.", token); - break; - case 'Number': - case 'String': - case 'Boolean': - case 'Math': - case 'JSON': - warning("Do not use {a} as a constructor.", token, c.value); + case "Number": + case "String": + case "Boolean": + case "Math": + case "JSON": + warning("Do not use {a} as a constructor.", prevtoken, c.value); break; - case 'Function': + case "Function": if (!option.evil) { warning("The Function constructor is eval."); } break; - case 'Date': - case 'RegExp': + case "Date": + case "RegExp": break; default: - if (c.id !== 'function') { + if (c.id !== "function") { i = c.value.substr(0, 1); - if (option.newcap && (i < 'A' || i > 'Z')) { + if (option.newcap && (i < "A" || i > "Z") && !is_own(global, c.value)) { warning("A constructor name should start with an uppercase letter.", token); } } } } else { - if (c.id !== '.' && c.id !== '[' && c.id !== '(') { + if (c.id !== "." && c.id !== "[" && c.id !== "(") { warning("Bad constructor.", token); } } @@ -2984,46 +3273,47 @@ loop: for (;;) { warning("Weird construction. Delete 'new'.", this); } adjacent(token, nexttoken); - if (nexttoken.id !== '(' && !option.supernew) { - warning("Missing '()' invoking a constructor."); + if (nexttoken.id !== "(" && !option.supernew) { + warning("Missing '()' invoking a constructor.", + token, token.value); } this.first = c; return this; }); - syntax['new'].exps = true; + syntax["new"].exps = true; - prefix('void').exps = true; + prefix("void").exps = true; - infix('.', function (left, that) { + infix(".", function (left, that) { adjacent(prevtoken, token); nobreak(); var m = identifier(); - if (typeof m === 'string') { + if (typeof m === "string") { countMember(m); } that.left = left; that.right = m; - if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) { + if (left && left.value === "arguments" && (m === "callee" || m === "caller")) { if (option.noarg) warning("Avoid arguments.{a}.", left, m); - else if (directive['use strict']) - error('Strict violation.'); - } else if (!option.evil && left && left.value === 'document' && - (m === 'write' || m === 'writeln')) { + else if (directive["use strict"]) + error("Strict violation."); + } else if (!option.evil && left && left.value === "document" && + (m === "write" || m === "writeln")) { warning("document.write can be a form of eval.", left); } - if (!option.evil && (m === 'eval' || m === 'execScript')) { - warning('eval is evil.'); + if (!option.evil && (m === "eval" || m === "execScript")) { + warning("eval is evil."); } return that; }, 160, true); - infix('(', function (left, that) { - if (prevtoken.id !== '}' && prevtoken.id !== ')') { + infix("(", function (left, that) { + if (prevtoken.id !== "}" && prevtoken.id !== ")") { nobreak(prevtoken, token); } nospace(); - if (option.immed && !left.immed && left.id === 'function') { + if (option.immed && !left.immed && left.id === "function") { warning("Wrap an immediate function invocation in parentheses " + "to assist the reader in understanding that the expression " + "is the result of a function, and not the function itself."); @@ -3031,51 +3321,63 @@ loop: for (;;) { var n = 0, p = []; if (left) { - if (left.type === '(identifier)') { + if (left.type === "(identifier)") { if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { - if (left.value !== 'Number' && left.value !== 'String' && - left.value !== 'Boolean' && - left.value !== 'Date') { - if (left.value === 'Math') { + if ("Number String Boolean Date Object".indexOf(left.value) === -1) { + if (left.value === "Math") { warning("Math is not a function.", left); } else if (option.newcap) { - warning( -"Missing 'new' prefix when invoking a constructor.", left); + warning("Missing 'new' prefix when invoking a constructor.", left); } } } } } - if (nexttoken.id !== ')') { + if (nexttoken.id !== ")") { for (;;) { p[p.length] = expression(10); n += 1; - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } comma(); } } - advance(')'); + advance(")"); nospace(prevtoken, token); - if (typeof left === 'object') { - if (left.value === 'parseInt' && n === 1) { - warning("Missing radix parameter.", left); + if (typeof left === "object") { + if (left.value === "parseInt" && n === 1) { + warning("Missing radix parameter.", token); } if (!option.evil) { - if (left.value === 'eval' || left.value === 'Function' || - left.value === 'execScript') { + if (left.value === "eval" || left.value === "Function" || + left.value === "execScript") { warning("eval is evil.", left); - } else if (p[0] && p[0].id === '(string)' && - (left.value === 'setTimeout' || - left.value === 'setInterval')) { + + if (p[0] && [0].id === "(string)") { + addInternalSrc(left, p[0].value); + } + } else if (p[0] && p[0].id === "(string)" && + (left.value === "setTimeout" || + left.value === "setInterval")) { warning( "Implied eval is evil. Pass a function instead of a string.", left); + addInternalSrc(left, p[0].value); + + // window.setTimeout/setInterval + } else if (p[0] && p[0].id === "(string)" && + left.value === "." && + left.left.value === "window" && + (left.right === "setTimeout" || + left.right === "setInterval")) { + warning( + "Implied eval is evil. Pass a function instead of a string.", left); + addInternalSrc(left, p[0].value); } } - if (!left.identifier && left.id !== '.' && left.id !== '[' && - left.id !== '(' && left.id !== '&&' && left.id !== '||' && - left.id !== '?') { + if (!left.identifier && left.id !== "." && left.id !== "[" && + left.id !== "(" && left.id !== "&&" && left.id !== "||" && + left.id !== "?") { warning("Bad invocation.", left); } } @@ -3083,34 +3385,32 @@ loop: for (;;) { return that; }, 155, true).exps = true; - prefix('(', function () { + prefix("(", function () { nospace(); - if (nexttoken.id === 'function') { + if (nexttoken.id === "function") { nexttoken.immed = true; } var v = expression(0); - advance(')', this); + advance(")", this); nospace(prevtoken, token); - if (option.immed && v.id === 'function') { - if (nexttoken.id === '(' || - (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) { - warning( -"Move the invocation into the parens that contain the function.", nexttoken); - } else { + if (option.immed && v.id === "function") { + if (nexttoken.id !== "(" && + (nexttoken.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) { warning( "Do not wrap function literals in parens unless they are to be immediately invoked.", this); } } + return v; }); - infix('[', function (left, that) { + infix("[", function (left, that) { nobreak(prevtoken, token); nospace(); var e = expression(0), s; - if (e && e.type === '(string)') { - if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) { + if (e && e.type === "(string)") { + if (!option.evil && (e.value === "eval" || e.value === "execScript")) { warning("eval is evil.", that); } countMember(e.value); @@ -3118,18 +3418,18 @@ loop: for (;;) { s = syntax[e.value]; if (!s || !s.reserved) { warning("['{a}'] is better written in dot notation.", - e, e.value); + prevtoken, e.value); } } } - advance(']', that); + advance("]", that); nospace(prevtoken, token); that.left = left; that.right = e; return that; }, 160, true); - prefix('[', function () { + prefix("[", function () { var b = token.line !== nexttoken.line; this.first = []; if (b) { @@ -3138,21 +3438,22 @@ loop: for (;;) { indent += option.indent; } } - while (nexttoken.id !== '(end)') { - while (nexttoken.id === ',') { - warning("Extra comma."); - advance(','); + while (nexttoken.id !== "(end)") { + while (nexttoken.id === ",") { + if (!option.es5) + warning("Extra comma."); + advance(","); } - if (nexttoken.id === ']') { + if (nexttoken.id === "]") { break; } if (b && token.line !== nexttoken.line) { indentation(); } this.first.push(expression(10)); - if (nexttoken.id === ',') { + if (nexttoken.id === ",") { comma(); - if (nexttoken.id === ']' && !option.es5) { + if (nexttoken.id === "]" && !option.es5) { warning("Extra comma.", token); break; } @@ -3164,7 +3465,7 @@ loop: for (;;) { indent -= option.indent; indentation(); } - advance(']', this); + advance("]", this); return this; }, 160); @@ -3172,10 +3473,10 @@ loop: for (;;) { function property_name() { var id = optionalidentifier(true); if (!id) { - if (nexttoken.id === '(string)') { + if (nexttoken.id === "(string)") { id = nexttoken.value; advance(); - } else if (nexttoken.id === '(number)') { + } else if (nexttoken.id === "(number)") { id = nexttoken.value.toString(); advance(); } @@ -3185,65 +3486,130 @@ loop: for (;;) { function functionparams() { - var i, t = nexttoken, p = []; - advance('('); + var next = nexttoken; + var params = []; + var ident; + + advance("("); nospace(); - if (nexttoken.id === ')') { - advance(')'); + + if (nexttoken.id === ")") { + advance(")"); return; } + for (;;) { - i = identifier(true); - p.push(i); - addlabel(i, 'parameter'); - if (nexttoken.id === ',') { + ident = identifier(true); + params.push(ident); + addlabel(ident, "unused", token); + if (nexttoken.id === ",") { comma(); } else { - advance(')', t); + advance(")", next); nospace(prevtoken, token); - return p; + return params; } } } - function doFunction(i, statement) { - var f, - oldOption = option, - oldScope = scope; + function doFunction(name, statement) { + var f; + var oldOption = option; + var oldScope = scope; option = Object.create(option); - scope = Object.create(scope); + scope = Object.create(scope); funct = { - '(name)' : i || '"' + anonname + '"', - '(line)' : nexttoken.line, - '(context)' : funct, - '(breakage)' : 0, - '(loopage)' : 0, - '(scope)' : scope, - '(statement)': statement + "(name)" : name || "\"" + anonname + "\"", + "(line)" : nexttoken.line, + "(character)": nexttoken.character, + "(context)" : funct, + "(breakage)" : 0, + "(loopage)" : 0, + "(metrics)" : createMetrics(nexttoken), + "(scope)" : scope, + "(statement)": statement, + "(tokens)" : {} }; + f = funct; token.funct = funct; + functions.push(funct); - if (i) { - addlabel(i, 'function'); + + if (name) { + addlabel(name, "function"); } - funct['(params)'] = functionparams(); + + funct["(params)"] = functionparams(); + funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]); block(false, false, true); + + funct["(metrics)"].verifyMaxStatementsPerFunction(); + funct["(metrics)"].verifyMaxComplexityPerFunction(); + scope = oldScope; option = oldOption; - funct['(last)'] = token.line; - funct = funct['(context)']; + funct["(last)"] = token.line; + funct["(lastcharacter)"] = token.character; + funct = funct["(context)"]; + return f; } + function createMetrics(functionStartToken) { + return { + statementCount: 0, + nestedBlockDepth: -1, + ComplexityCount: 1, + verifyMaxStatementsPerFunction: function () { + if (option.maxstatements && + this.statementCount > option.maxstatements) { + var message = "Too many statements per function (" + this.statementCount + ")."; + warning(message, functionStartToken); + } + }, + + verifyMaxParametersPerFunction: function (params) { + params = params || []; + + if (option.maxparams && params.length > option.maxparams) { + var message = "Too many parameters per function (" + params.length + ")."; + warning(message, functionStartToken); + } + }, + + verifyMaxNestedBlockDepthPerFunction: function () { + if (option.maxdepth && + this.nestedBlockDepth > 0 && + this.nestedBlockDepth === option.maxdepth + 1) { + var message = "Blocks are nested too deeply (" + this.nestedBlockDepth + ")."; + warning(message); + } + }, + + verifyMaxComplexityPerFunction: function () { + var max = option.maxcomplexity; + var cc = this.ComplexityCount; + if (max && cc > max) { + var message = "Cyclomatic complexity is too high per function (" + cc + ")."; + warning(message, functionStartToken); + } + } + }; + } + + function increaseComplexityCount() { + funct["(metrics)"].ComplexityCount += 1; + } + (function (x) { x.nud = function () { - var b, f, i, j, p, t; + var b, f, i, p, t; var props = {}; // All properties, including accessors function saveProperty(name, token) { @@ -3288,14 +3654,14 @@ loop: for (;;) { } } for (;;) { - if (nexttoken.id === '}') { + if (nexttoken.id === "}") { break; } if (b) { indentation(); } - if (nexttoken.value === 'get' && peek().id !== ':') { - advance('get'); + if (nexttoken.value === "get" && peek().id !== ":") { + advance("get"); if (!option.es5) { error("get/set are ES5 features."); } @@ -3307,13 +3673,13 @@ loop: for (;;) { t = nexttoken; adjacent(token, nexttoken); f = doFunction(); - p = f['(params)']; + p = f["(params)"]; if (p) { warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); } adjacent(token, nexttoken); - } else if (nexttoken.value === 'set' && peek().id !== ':') { - advance('set'); + } else if (nexttoken.value === "set" && peek().id !== ":") { + advance("set"); if (!option.es5) { error("get/set are ES5 features."); } @@ -3325,27 +3691,27 @@ loop: for (;;) { t = nexttoken; adjacent(token, nexttoken); f = doFunction(); - p = f['(params)']; + p = f["(params)"]; if (!p || p.length !== 1) { warning("Expected a single parameter in set {a} function.", t, i); } } else { i = property_name(); saveProperty(i, nexttoken); - if (typeof i !== 'string') { + if (typeof i !== "string") { break; } - advance(':'); + advance(":"); nonadjacent(token, nexttoken); expression(10); } countMember(i); - if (nexttoken.id === ',') { + if (nexttoken.id === ",") { comma(); - if (nexttoken.id === ',') { + if (nexttoken.id === ",") { warning("Extra comma.", token); - } else if (nexttoken.id === '}' && !option.es5) { + } else if (nexttoken.id === "}" && !option.es5) { warning("Extra comma.", token); } } else { @@ -3356,7 +3722,7 @@ loop: for (;;) { indent -= option.indent; indentation(); } - advance('}', this); + advance("}", this); // Check for lonely setters if in the ES5 mode. if (option.es5) { @@ -3371,13 +3737,13 @@ loop: for (;;) { x.fud = function () { error("Expected to see a statement and instead saw a block.", token); }; - }(delim('{'))); + }(delim("{"))); // This Function is called when esnext option is set to true // it adds the `const` statement to JSHINT useESNextSyntax = function () { - var conststatement = stmt('const', function (prefix) { + var conststatement = stmt("const", function (prefix) { var id, name, value; this.first = []; @@ -3387,10 +3753,10 @@ loop: for (;;) { if (funct[id] === "const") { warning("const '" + id + "' has already been declared"); } - if (funct['(global)'] && predefined[id] === false) { + if (funct["(global)"] && predefined[id] === false) { warning("Redefinition of '{a}'.", token, id); } - addlabel(id, 'const'); + addlabel(id, "const"); if (prefix) { break; } @@ -3402,15 +3768,15 @@ loop: for (;;) { "'{a}' is initialized to 'undefined'.", token, id); } - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { nonadjacent(token, nexttoken); - advance('='); + advance("="); nonadjacent(token, nexttoken); - if (nexttoken.id === 'undefined') { + if (nexttoken.id === "undefined") { warning("It is not necessary to initialize " + "'{a}' to 'undefined'.", token, id); } - if (peek(0).id === '=' && nexttoken.identifier) { + if (peek(0).id === "=" && nexttoken.identifier) { error("Constant {a} was not declared correctly.", nexttoken, nexttoken.value); } @@ -3418,7 +3784,7 @@ loop: for (;;) { name.first = value; } - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } comma(); @@ -3428,47 +3794,55 @@ loop: for (;;) { conststatement.exps = true; }; - var varstatement = stmt('var', function (prefix) { + var varstatement = stmt("var", function (prefix) { // JavaScript does not have block scope. It only has function scope. So, // declaring a variable in a block can have unexpected consequences. var id, name, value; - if (funct['(onevar)'] && option.onevar) { + if (funct["(onevar)"] && option.onevar) { warning("Too many var statements."); - } else if (!funct['(global)']) { - funct['(onevar)'] = true; + } else if (!funct["(global)"]) { + funct["(onevar)"] = true; } + this.first = []; + for (;;) { nonadjacent(token, nexttoken); id = identifier(); + if (option.esnext && funct[id] === "const") { warning("const '" + id + "' has already been declared"); } - if (funct['(global)'] && predefined[id] === false) { + + if (funct["(global)"] && predefined[id] === false) { warning("Redefinition of '{a}'.", token, id); } - addlabel(id, 'unused'); + + addlabel(id, "unused", token); + if (prefix) { break; } + name = token; this.first.push(token); - if (nexttoken.id === '=') { + + if (nexttoken.id === "=") { nonadjacent(token, nexttoken); - advance('='); + advance("="); nonadjacent(token, nexttoken); - if (nexttoken.id === 'undefined') { + if (nexttoken.id === "undefined") { warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); } - if (peek(0).id === '=' && nexttoken.identifier) { + if (peek(0).id === "=" && nexttoken.identifier) { error("Variable {a} was not declared correctly.", nexttoken, nexttoken.value); } value = expression(0); name.first = value; } - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } comma(); @@ -3477,7 +3851,7 @@ loop: for (;;) { }); varstatement.exps = true; - blockstmt('function', function () { + blockstmt("function", function () { if (inblock) { warning("Function declarations should not be placed in blocks. " + "Use a function expression or move the statement to the top of " + @@ -3489,16 +3863,17 @@ loop: for (;;) { warning("const '" + i + "' has already been declared"); } adjacent(token, nexttoken); - addlabel(i, 'unction'); - doFunction(i, true); - if (nexttoken.id === '(' && nexttoken.line === token.line) { + addlabel(i, "unction", token); + + doFunction(i, { statement: true }); + if (nexttoken.id === "(" && nexttoken.line === token.line) { error( "Function declarations are not invocable. Wrap the whole function invocation in parens."); } return this; }); - prefix('function', function () { + prefix("function", function () { var i = optionalidentifier(); if (i) { adjacent(token, nexttoken); @@ -3506,31 +3881,32 @@ loop: for (;;) { nonadjacent(token, nexttoken); } doFunction(i); - if (!option.loopfunc && funct['(loopage)']) { + if (!option.loopfunc && funct["(loopage)"]) { warning("Don't make functions within a loop."); } return this; }); - blockstmt('if', function () { + blockstmt("if", function () { var t = nexttoken; - advance('('); + increaseComplexityCount(); + advance("("); nonadjacent(this, t); nospace(); expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } - advance(')', t); + advance(")", t); nospace(prevtoken, token); block(true, true); - if (nexttoken.id === 'else') { + if (nexttoken.id === "else") { nonadjacent(token, nexttoken); - advance('else'); - if (nexttoken.id === 'if' || nexttoken.id === 'switch') { + advance("else"); + if (nexttoken.id === "if" || nexttoken.id === "switch") { statement(true); } else { block(true, true); @@ -3539,90 +3915,146 @@ loop: for (;;) { return this; }); - blockstmt('try', function () { - var b, e, s; + blockstmt("try", function () { + var b; - block(false); - if (nexttoken.id === 'catch') { - advance('catch'); + function doCatch() { + var oldScope = scope; + var e; + + advance("catch"); nonadjacent(token, nexttoken); - advance('('); - s = scope; - scope = Object.create(s); + advance("("); + + scope = Object.create(oldScope); + e = nexttoken.value; - if (nexttoken.type !== '(identifier)') { - warning("Expected an identifier and instead saw '{a}'.", - nexttoken, e); - } else { - addlabel(e, 'exception'); + if (nexttoken.type !== "(identifier)") { + e = null; + warning("Expected an identifier and instead saw '{a}'.", nexttoken, e); } + advance(); - advance(')'); + advance(")"); + + funct = { + "(name)" : "(catch)", + "(line)" : nexttoken.line, + "(character)": nexttoken.character, + "(context)" : funct, + "(breakage)" : funct["(breakage)"], + "(loopage)" : funct["(loopage)"], + "(scope)" : scope, + "(statement)": false, + "(metrics)" : createMetrics(nexttoken), + "(catch)" : true, + "(tokens)" : {} + }; + + if (e) { + addlabel(e, "exception"); + } + + token.funct = funct; + functions.push(funct); + block(false); + + scope = oldScope; + + funct["(last)"] = token.line; + funct["(lastcharacter)"] = token.character; + funct = funct["(context)"]; + } + + block(false); + + if (nexttoken.id === "catch") { + increaseComplexityCount(); + doCatch(); b = true; - scope = s; } - if (nexttoken.id === 'finally') { - advance('finally'); + + if (nexttoken.id === "finally") { + advance("finally"); block(false); return; } else if (!b) { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'catch', nexttoken.value); + nexttoken, "catch", nexttoken.value); } + return this; }); - blockstmt('while', function () { + blockstmt("while", function () { var t = nexttoken; - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - advance('('); + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); nonadjacent(this, t); nospace(); expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } - advance(')', t); + advance(")", t); nospace(prevtoken, token); block(true, true); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; }).labelled = true; - reserve('with'); + blockstmt("with", function () { + var t = nexttoken; + if (directive["use strict"]) { + error("'with' is not allowed in strict mode.", token); + } else if (!option.withstmt) { + warning("Don't use 'with'.", token); + } - blockstmt('switch', function () { + advance("("); + nonadjacent(this, t); + nospace(); + expression(0); + advance(")", t); + nospace(prevtoken, token); + block(true, true); + + return this; + }); + + blockstmt("switch", function () { var t = nexttoken, g = false; - funct['(breakage)'] += 1; - advance('('); + funct["(breakage)"] += 1; + advance("("); nonadjacent(this, t); nospace(); this.condition = expression(20); - advance(')', t); + advance(")", t); nospace(prevtoken, token); nonadjacent(token, nexttoken); t = nexttoken; - advance('{'); + advance("{"); nonadjacent(token, nexttoken); indent += option.indent; this.cases = []; for (;;) { switch (nexttoken.id) { - case 'case': - switch (funct['(verb)']) { - case 'break': - case 'case': - case 'continue': - case 'return': - case 'switch': - case 'throw': + case "case": + switch (funct["(verb)"]) { + case "break": + case "case": + case "continue": + case "return": + case "switch": + case "throw": break; default: // You can tell JSHint that you don't use break intentionally by @@ -3635,18 +4067,19 @@ loop: for (;;) { } } indentation(-option.indent); - advance('case'); + advance("case"); this.cases.push(expression(20)); + increaseComplexityCount(); g = true; - advance(':'); - funct['(verb)'] = 'case'; + advance(":"); + funct["(verb)"] = "case"; break; - case 'default': - switch (funct['(verb)']) { - case 'break': - case 'continue': - case 'return': - case 'throw': + case "default": + switch (funct["(verb)"]) { + case "break": + case "continue": + case "return": + case "throw": break; default: if (!ft.test(lines[nexttoken.line - 2])) { @@ -3656,32 +4089,32 @@ loop: for (;;) { } } indentation(-option.indent); - advance('default'); + advance("default"); g = true; - advance(':'); + advance(":"); break; - case '}': + case "}": indent -= option.indent; indentation(); - advance('}', t); - if (this.cases.length === 1 || this.condition.id === 'true' || - this.condition.id === 'false') { + advance("}", t); + if (this.cases.length === 1 || this.condition.id === "true" || + this.condition.id === "false") { if (!option.onecase) warning("This 'switch' should be an 'if'.", this); } - funct['(breakage)'] -= 1; - funct['(verb)'] = undefined; + funct["(breakage)"] -= 1; + funct["(verb)"] = undefined; return; - case '(end)': - error("Missing '{a}'.", nexttoken, '}'); + case "(end)": + error("Missing '{a}'.", nexttoken, "}"); return; default: if (g) { switch (token.id) { - case ',': + case ",": error("Each value should have its own case label."); return; - case ':': + case ":": g = false; statements(); break; @@ -3690,13 +4123,13 @@ loop: for (;;) { return; } } else { - if (token.id === ':') { - advance(':'); - error("Unexpected '{a}'.", token, ':'); + if (token.id === ":") { + advance(":"); + error("Unexpected '{a}'.", token, ":"); statements(); } else { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'case', nexttoken.value); + nexttoken, "case", nexttoken.value); return; } } @@ -3704,7 +4137,7 @@ loop: for (;;) { } }).labelled = true; - stmt('debugger', function () { + stmt("debugger", function () { if (!option.debug) { warning("All 'debugger' statements should be removed."); } @@ -3712,49 +4145,52 @@ loop: for (;;) { }).exps = true; (function () { - var x = stmt('do', function () { - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; + var x = stmt("do", function () { + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + this.first = block(true); - advance('while'); + advance("while"); var t = nexttoken; nonadjacent(token, t); - advance('('); + advance("("); nospace(); expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } - advance(')', t); + advance(")", t); nospace(prevtoken, token); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; }); x.labelled = true; x.exps = true; }()); - blockstmt('for', function () { + blockstmt("for", function () { var s, t = nexttoken; - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - advance('('); + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); nonadjacent(this, t); nospace(); - if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { - if (nexttoken.id === 'var') { - advance('var'); + if (peek(nexttoken.id === "var" ? 1 : 0).id === "in") { + if (nexttoken.id === "var") { + advance("var"); varstatement.fud.call(varstatement, true); } else { switch (funct[nexttoken.value]) { - case 'unused': - funct[nexttoken.value] = 'var'; + case "unused": + funct[nexttoken.value] = "var"; break; - case 'var': + case "var": break; default: warning("Bad for in variable '{a}'.", @@ -3762,27 +4198,27 @@ loop: for (;;) { } advance(); } - advance('in'); + advance("in"); expression(20); - advance(')', t); + advance(")", t); s = block(true, true); - if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' || - s[0].value !== 'if')) { + if (option.forin && s && (s.length > 1 || typeof s[0] !== "object" || + s[0].value !== "if")) { warning("The body of a for in should be wrapped in an if statement to filter " + "unwanted properties from the prototype.", this); } - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; } else { - if (nexttoken.id !== ';') { - if (nexttoken.id === 'var') { - advance('var'); + if (nexttoken.id !== ";") { + if (nexttoken.id === "var") { + advance("var"); varstatement.fud.call(varstatement); } else { for (;;) { - expression(0, 'for'); - if (nexttoken.id !== ',') { + expression(0, "for"); + if (nexttoken.id !== ",") { break; } comma(); @@ -3790,53 +4226,53 @@ loop: for (;;) { } } nolinebreak(token); - advance(';'); - if (nexttoken.id !== ';') { + advance(";"); + if (nexttoken.id !== ";") { expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } } nolinebreak(token); - advance(';'); - if (nexttoken.id === ';') { + advance(";"); + if (nexttoken.id === ";") { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, ')', ';'); + nexttoken, ")", ";"); } - if (nexttoken.id !== ')') { + if (nexttoken.id !== ")") { for (;;) { - expression(0, 'for'); - if (nexttoken.id !== ',') { + expression(0, "for"); + if (nexttoken.id !== ",") { break; } comma(); } } - advance(')', t); + advance(")", t); nospace(prevtoken, token); block(true, true); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; } }).labelled = true; - stmt('break', function () { + stmt("break", function () { var v = nexttoken.value; - if (funct['(breakage)'] === 0) + if (funct["(breakage)"] === 0) warning("Unexpected '{a}'.", nexttoken, this.value); if (!option.asi) nolinebreak(this); - if (nexttoken.id !== ';') { + if (nexttoken.id !== ";") { if (token.line === nexttoken.line) { - if (funct[v] !== 'label') { + if (funct[v] !== "label") { warning("'{a}' is not a statement label.", nexttoken, v); } else if (scope[v] !== funct) { warning("'{a}' is out of scope.", nexttoken, v); @@ -3845,23 +4281,23 @@ loop: for (;;) { advance(); } } - reachable('break'); + reachable("break"); return this; }).exps = true; - stmt('continue', function () { + stmt("continue", function () { var v = nexttoken.value; - if (funct['(breakage)'] === 0) + if (funct["(breakage)"] === 0) warning("Unexpected '{a}'.", nexttoken, this.value); if (!option.asi) nolinebreak(this); - if (nexttoken.id !== ';') { + if (nexttoken.id !== ";") { if (token.line === nexttoken.line) { - if (funct[v] !== 'label') { + if (funct[v] !== "label") { warning("'{a}' is not a statement label.", nexttoken, v); } else if (scope[v] !== funct) { warning("'{a}' is out of scope.", nexttoken, v); @@ -3869,20 +4305,20 @@ loop: for (;;) { this.first = nexttoken; advance(); } - } else if (!funct['(loopage)']) { + } else if (!funct["(loopage)"]) { warning("Unexpected '{a}'.", nexttoken, this.value); } - reachable('continue'); + reachable("continue"); return this; }).exps = true; - stmt('return', function () { + stmt("return", function () { if (this.line === nexttoken.line) { - if (nexttoken.id === '(regexp)') + if (nexttoken.id === "(regexp)") warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); - if (nexttoken.id !== ';' && !nexttoken.reach) { + if (nexttoken.id !== ";" && !nexttoken.reach) { nonadjacent(token, nexttoken); if (peek().value === "=" && !option.boss) { warningAt("Did you mean to return a conditional instead of an assignment?", @@ -3893,38 +4329,38 @@ loop: for (;;) { } else if (!option.asi) { nolinebreak(this); // always warn (Line breaking error) } - reachable('return'); + reachable("return"); return this; }).exps = true; - stmt('throw', function () { + stmt("throw", function () { nolinebreak(this); nonadjacent(token, nexttoken); this.first = expression(20); - reachable('throw'); + reachable("throw"); return this; }).exps = true; // Superfluous reserved words - reserve('class'); - reserve('const'); - reserve('enum'); - reserve('export'); - reserve('extends'); - reserve('import'); - reserve('super'); - - reserve('let'); - reserve('yield'); - reserve('implements'); - reserve('interface'); - reserve('package'); - reserve('private'); - reserve('protected'); - reserve('public'); - reserve('static'); + reserve("class"); + reserve("const"); + reserve("enum"); + reserve("export"); + reserve("extends"); + reserve("import"); + reserve("super"); + + reserve("let"); + reserve("yield"); + reserve("implements"); + reserve("interface"); + reserve("package"); + reserve("private"); + reserve("protected"); + reserve("public"); + reserve("static"); // Parse JSON @@ -3933,26 +4369,26 @@ loop: for (;;) { function jsonObject() { var o = {}, t = nexttoken; - advance('{'); - if (nexttoken.id !== '}') { + advance("{"); + if (nexttoken.id !== "}") { for (;;) { - if (nexttoken.id === '(end)') { + if (nexttoken.id === "(end)") { error("Missing '}' to match '{' from line {a}.", nexttoken, t.line); - } else if (nexttoken.id === '}') { + } else if (nexttoken.id === "}") { warning("Unexpected comma.", token); break; - } else if (nexttoken.id === ',') { + } else if (nexttoken.id === ",") { error("Unexpected comma.", nexttoken); - } else if (nexttoken.id !== '(string)') { + } else if (nexttoken.id !== "(string)") { warning("Expected a string and instead saw {a}.", nexttoken, nexttoken.value); } if (o[nexttoken.value] === true) { warning("Duplicate key '{a}'.", nexttoken, nexttoken.value); - } else if ((nexttoken.value === '__proto__' && - !option.proto) || (nexttoken.value === '__iterator__' && + } else if ((nexttoken.value === "__proto__" && + !option.proto) || (nexttoken.value === "__iterator__" && !option.iterator)) { warning("The '{a}' key may produce unexpected results.", nexttoken, nexttoken.value); @@ -3960,62 +4396,62 @@ loop: for (;;) { o[nexttoken.value] = true; } advance(); - advance(':'); + advance(":"); jsonValue(); - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } - advance(','); + advance(","); } } - advance('}'); + advance("}"); } function jsonArray() { var t = nexttoken; - advance('['); - if (nexttoken.id !== ']') { + advance("["); + if (nexttoken.id !== "]") { for (;;) { - if (nexttoken.id === '(end)') { + if (nexttoken.id === "(end)") { error("Missing ']' to match '[' from line {a}.", nexttoken, t.line); - } else if (nexttoken.id === ']') { + } else if (nexttoken.id === "]") { warning("Unexpected comma.", token); break; - } else if (nexttoken.id === ',') { + } else if (nexttoken.id === ",") { error("Unexpected comma.", nexttoken); } jsonValue(); - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } - advance(','); + advance(","); } } - advance(']'); + advance("]"); } switch (nexttoken.id) { - case '{': + case "{": jsonObject(); break; - case '[': + case "[": jsonArray(); break; - case 'true': - case 'false': - case 'null': - case '(number)': - case '(string)': + case "true": + case "false": + case "null": + case "(number)": + case "(string)": advance(); break; - case '-': - advance('-'); + case "-": + advance("-"); if (token.character !== nexttoken.from) { warning("Unexpected space after '-'.", token); } adjacent(token, nexttoken); - advance('(number)'); + advance("(number)"); break; default: error("Expected a JSON value.", nexttoken); @@ -4023,48 +4459,75 @@ loop: for (;;) { } -// The actual JSHINT function itself. - + // The actual JSHINT function itself. var itself = function (s, o, g) { - var a, i, k; - JSHINT.errors = []; - JSHINT.undefs = []; + var a, i, k, x; + var optionKeys; + var newOptionObj = {}; + + if (o && o.scope) { + JSHINT.scope = o.scope; + } else { + JSHINT.errors = []; + JSHINT.undefs = []; + JSHINT.internals = []; + JSHINT.blacklist = {}; + JSHINT.scope = "(main)"; + } + predefined = Object.create(standard); + declared = Object.create(null); combine(predefined, g || {}); + if (o) { a = o.predef; if (a) { - if (Array.isArray(a)) { - for (i = 0; i < a.length; i += 1) { - predefined[a[i]] = true; - } - } else if (typeof a === 'object') { - k = Object.keys(a); - for (i = 0; i < k.length; i += 1) { - predefined[k[i]] = !!a[k[i]]; - } + if (!Array.isArray(a) && typeof a === "object") { + a = Object.keys(a); } + a.forEach(function (item) { + var slice; + if (item[0] === "-") { + slice = item.slice(1); + JSHINT.blacklist[slice] = slice; + } else { + predefined[item] = true; + } + }); + } + + optionKeys = Object.keys(o); + for (x = 0; x < optionKeys.length; x++) { + newOptionObj[optionKeys[x]] = o[optionKeys[x]]; + + if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false) + newOptionObj["(explicitNewcap)"] = true; + + if (optionKeys[x] === "indent") + newOptionObj.white = true; } - option = o; - } else { - option = {}; } + + option = newOptionObj; + option.indent = option.indent || 4; option.maxerr = option.maxerr || 50; - tab = ''; + tab = ""; for (i = 0; i < option.indent; i += 1) { - tab += ' '; + tab += " "; } indent = 1; global = Object.create(predefined); scope = global; funct = { - '(global)': true, - '(name)': '(global)', - '(scope)': scope, - '(breakage)': 0, - '(loopage)': 0 + "(global)": true, + "(name)": "(global)", + "(scope)": scope, + "(breakage)": 0, + "(loopage)": 0, + "(tokens)": {}, + "(metrics)": createMetrics(nexttoken) }; functions = [funct]; urls = []; @@ -4076,21 +4539,52 @@ loop: for (;;) { lookahead = []; jsonmode = false; warnings = 0; + lines = []; + unuseds = []; + + if (!isString(s) && !Array.isArray(s)) { + errorAt("Input is neither a string nor an array of strings.", 0); + return false; + } + + if (isString(s) && /^\s*$/g.test(s)) { + errorAt("Input is an empty string.", 0); + return false; + } + + if (s.length === 0) { + errorAt("Input is an empty array.", 0); + return false; + } + lex.init(s); + prereg = true; directive = {}; - prevtoken = token = nexttoken = syntax['(begin)']; + prevtoken = token = nexttoken = syntax["(begin)"]; + + // Check options + for (var name in o) { + if (is_own(o, name)) { + checkOption(name, token); + } + } + assume(); // combine the passed globals after we've assumed all our options combine(predefined, g || {}); + //reset values + comma.first = true; + quotmark = undefined; + try { advance(); switch (nexttoken.id) { - case '{': - case '[': + case "{": + case "[": option.laxbreak = true; jsonmode = true; jsonValue(); @@ -4103,26 +4597,26 @@ loop: for (;;) { statements(); } - advance('(end)'); + advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined); var markDefined = function (name, context) { do { - if (typeof context[name] === 'string') { + if (typeof context[name] === "string") { // JSHINT marks unused variables as 'unused' and // unused function declaration as 'unction'. This // code changes such instances back 'var' and // 'closure' so that the code in JSHINT.data() // doesn't think they're unused. - if (context[name] === 'unused') - context[name] = 'var'; - else if (context[name] === 'unction') - context[name] = 'closure'; + if (context[name] === "unused") + context[name] = "var"; + else if (context[name] === "unction") + context[name] = "closure"; return true; } - context = context['(context)']; + context = context["(context)"]; } while (context); return false; @@ -4144,6 +4638,37 @@ loop: for (;;) { implied[name] = newImplied; }; + var warnUnused = function (name, token) { + var line = token.line; + var chr = token.character; + + if (option.unused) + warningAt("'{a}' is defined but never used.", line, chr, name); + + unuseds.push({ + name: name, + line: line, + character: chr + }); + }; + + var checkUnused = function (func, key) { + var type = func[key]; + var token = func["(tokens)"][key]; + + if (key.charAt(0) === "(") + return; + + if (type !== "unused" && type !== "unction") + return; + + // Params are checked separately from other variables. + if (func["(params)"] && func["(params)"].indexOf(key) !== -1) + return; + + warnUnused(key, token); + }; + // Check queued 'x is not defined' instances to see if they're still undefined. for (i = 0; i < JSHINT.undefs.length; i += 1) { k = JSHINT.undefs[i].slice(0); @@ -4154,6 +4679,43 @@ loop: for (;;) { warning.apply(warning, k.slice(1)); } } + + functions.forEach(function (func) { + for (var key in func) { + if (is_own(func, key)) { + checkUnused(func, key); + } + } + + if (!func["(params)"]) + return; + + var params = func["(params)"].slice(); + var param = params.pop(); + var type; + + while (param) { + type = func[param]; + + // 'undefined' is a special case for (function (window, undefined) { ... })(); + // patterns. + + if (param === "undefined") + return; + + if (type !== "unused" && type !== "unction") + return; + + warnUnused(param, func["(tokens)"][param]); + param = params.pop(); + } + }); + + for (var key in declared) { + if (is_own(declared, key) && !is_own(global, key)) { + warnUnused(key, declared[key]); + } + } } catch (e) { if (e) { var nt = nexttoken || {}; @@ -4166,14 +4728,31 @@ loop: for (;;) { } } + // Loop over the listed "internals", and check them as well. + + if (JSHINT.scope === "(main)") { + o = o || {}; + + for (i = 0; i < JSHINT.internals.length; i += 1) { + k = JSHINT.internals[i]; + o.scope = k.elem; + itself(k.value, o, g); + } + } + return JSHINT.errors.length === 0; }; // Data summary. itself.data = function () { + var data = { + functions: [], + options: option + }; + var implieds = []; + var members = []; + var fu, f, i, j, n, globals; - var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j, - members = [], n, unused = [], v; if (itself.errors.length) { data.errors = itself.errors; } @@ -4190,6 +4769,7 @@ loop: for (;;) { }); } } + if (implieds.length > 0) { data.implieds = implieds; } @@ -4202,49 +4782,37 @@ loop: for (;;) { if (globals.length > 0) { data.globals = globals; } + for (i = 1; i < functions.length; i += 1) { f = functions[i]; fu = {}; + for (j = 0; j < functionicity.length; j += 1) { fu[functionicity[j]] = []; } - for (n in f) { - if (is_own(f, n) && n.charAt(0) !== '(') { - v = f[n]; - if (v === 'unction') { - v = 'unused'; - } - if (Array.isArray(fu[v])) { - fu[v].push(n); - if (v === 'unused') { - unused.push({ - name: n, - line: f['(line)'], - 'function': f['(name)'] - }); - } - } - } - } + for (j = 0; j < functionicity.length; j += 1) { if (fu[functionicity[j]].length === 0) { delete fu[functionicity[j]]; } } - fu.name = f['(name)']; - fu.param = f['(params)']; - fu.line = f['(line)']; - fu.last = f['(last)']; + + fu.name = f["(name)"]; + fu.param = f["(params)"]; + fu.line = f["(line)"]; + fu.character = f["(character)"]; + fu.last = f["(last)"]; + fu.lastcharacter = f["(lastcharacter)"]; data.functions.push(fu); } - if (unused.length > 0) { - data.unused = unused; + if (unuseds.length > 0) { + data.unused = unuseds; } members = []; for (n in member) { - if (typeof member[n] === 'number') { + if (typeof member[n] === "number") { data.member = member; break; } @@ -4253,138 +4821,12 @@ loop: for (;;) { return data; }; - itself.report = function (option) { - var data = itself.data(); - - var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s; - - function detail(h, array) { - var b, i, singularity; - if (array) { - o.push('
' + h + ' '); - array = array.sort(); - for (i = 0; i < array.length; i += 1) { - if (array[i] !== singularity) { - singularity = array[i]; - o.push((b ? ', ' : '') + singularity); - b = true; - } - } - o.push('
'); - } - } - - - if (data.errors || data.implieds || data.unused) { - err = true; - o.push('
Error:'); - if (data.errors) { - for (i = 0; i < data.errors.length; i += 1) { - c = data.errors[i]; - if (c) { - e = c.evidence || ''; - o.push('

Problem' + (isFinite(c.line) ? ' at line ' + - c.line + ' character ' + c.character : '') + - ': ' + c.reason.entityify() + - '

' + - (e && (e.length > 80 ? e.slice(0, 77) + '...' : - e).entityify()) + '

'); - } - } - } - - if (data.implieds) { - s = []; - for (i = 0; i < data.implieds.length; i += 1) { - s[i] = '' + data.implieds[i].name + ' ' + - data.implieds[i].line + ''; - } - o.push('

Implied global: ' + s.join(', ') + '

'); - } - - if (data.unused) { - s = []; - for (i = 0; i < data.unused.length; i += 1) { - s[i] = '' + data.unused[i].name + ' ' + - data.unused[i].line + ' ' + - data.unused[i]['function'] + ''; - } - o.push('

Unused variable: ' + s.join(', ') + '

'); - } - if (data.json) { - o.push('

JSON: bad.

'); - } - o.push('
'); - } - - if (!option) { - - o.push('
'); - - if (data.urls) { - detail("URLs
", data.urls, '
'); - } - - if (data.json && !err) { - o.push('

JSON: good.

'); - } else if (data.globals) { - o.push('
Global ' + - data.globals.sort().join(', ') + '
'); - } else { - o.push('
No new global variables introduced.
'); - } - - for (i = 0; i < data.functions.length; i += 1) { - f = data.functions[i]; - - o.push('
' + f.line + '-' + - f.last + ' ' + (f.name || '') + '(' + - (f.param ? f.param.join(', ') : '') + ')
'); - detail('Unused', f.unused); - detail('Closure', f.closure); - detail('Variable', f['var']); - detail('Exception', f.exception); - detail('Outer', f.outer); - detail('Global', f.global); - detail('Label', f.label); - } - - if (data.member) { - a = Object.keys(data.member); - if (a.length) { - a = a.sort(); - m = '
/*members ';
-                    l = 10;
-                    for (i = 0; i < a.length; i += 1) {
-                        k = a[i];
-                        n = k.name();
-                        if (l + n.length > 72) {
-                            o.push(m + '
'); - m = ' '; - l = 1; - } - l += n.length + 2; - if (data.member[k] === 1) { - n = '' + n + ''; - } - if (i < a.length - 1) { - n += ', '; - } - m += n; - } - o.push(m + '
*/
'); - } - o.push('
'); - } - } - return o.join(''); - }; - itself.jshint = itself; return itself; }()); // Make JSHINT a Node module, if possible. -if (typeof exports === 'object' && exports) +if (typeof exports === "object" && exports) { exports.JSHINT = JSHINT; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/README.md index 7e061aa..f97e240 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/README.md @@ -12,7 +12,7 @@ Default Usage: they should be ".js". Anything else is assumed to be some kind of shell script, which should have a shebang line. 3. `npm install tap` -4. `tap ./tests` +4. `tap ./test` The output will be TAP-compliant. @@ -75,7 +75,7 @@ this is very useful for CI systems and such. ## Experimental Code Coverage with runforcover & bunker: ``` -TAP_COV=1 tap ./tests [--cover=./lib,foo.js] [--cover-dir=./coverage] +TAP_COV=1 tap ./test [--cover=./lib,foo.js] [--cover-dir=./coverage] ``` This feature is experimental, and will most likely change somewhat diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-assert.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-assert.js index bde5f11..60203a0 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-assert.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-assert.js @@ -2,6 +2,7 @@ var difflet = require('difflet') , deepEqual = require('deep-equal') , bufferEqual = require('buffer-equal') + , Buffer = require('buffer').Buffer module.exports = assert @@ -202,6 +203,8 @@ function inequal (a, b, message, extra) { assert.inequal = inequal syns.inequal = ["notEqual" ,"notEquals" + ,"notStrictEqual" + ,"notStrictEquals" ,"isNotEqual" ,"isNot" ,"not" diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-browser-harness.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-browser-harness.js index 6e6cda7..94700f5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-browser-harness.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-browser-harness.js @@ -30,7 +30,7 @@ function BrowserHarness (outPipe) { //console.error(child.results) // write out the stuff for this child. //console.error("child.conf", child.conf) - output.write(child.conf.name || "(unnamed test)") + // maybe write some other stuff about the number of tests in this // thing, etc. I dunno. //console.error("child results", child.results) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-consumer.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-consumer.js index 3fd8fea..f1b2a6a 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-consumer.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-consumer.js @@ -215,7 +215,9 @@ TapConsumer.prototype._parseIndented = function () { //console.error(ind, this._indent) for (var i = 0, l = ind.length; i < l; i ++) { var line = ind[i] - , lt = line.trim() + if (line === undefined) continue + var lt = line.trim() + if (!ys) { ys = line.match(/^(\s*)---(.*)$/) if (ys) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-global-harness.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-global-harness.js index 0bcb3a4..1007300 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-global-harness.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-global-harness.js @@ -34,7 +34,7 @@ function GlobalHarness () { //console.error(child.results) // write out the stuff for this child. //console.error("child.conf", child.conf) - output.write(child.conf.name || "(unnamed test)") + // maybe write some other stuff about the number of tests in this // thing, etc. I dunno. //console.error("child results", child.results) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-harness.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-harness.js index b56e567..3c0eb80 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-harness.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-harness.js @@ -140,6 +140,8 @@ Harness.prototype.childEnd = function (child) { this._testCount ++ this._planSum += child._plan //console.error("adding set of child.results") + + this.results.add(child.conf.name || "(unnamed test)") this.results.addSet(child.results) this.emit("childEnd", child) // was this planned? diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/package.json index 1691947..2c6ad5d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/package.json @@ -31,6 +31,7 @@ "url": "http://substack.net" }, "readme": "buffer-equal\n============\n\nReturn whether two buffers are equal.\n\n[![build status](https://secure.travis-ci.org/substack/node-buffer-equal.png)](http://travis-ci.org/substack/node-buffer-equal)\n\nexample\n=======\n\n``` js\nvar bufferEqual = require('bufferEqual');\n\nconsole.dir(bufferEqual(\n new Buffer([253,254,255]),\n new Buffer([253,254,255])\n));\nconsole.dir(bufferEqual(\n new Buffer('abc'),\n new Buffer('abcd')\n));\nconsole.dir(bufferEqual(\n new Buffer('abc'),\n 'abc'\n));\n```\n\noutput:\n\n```\ntrue\nfalse\nundefined\n```\n\nmethods\n=======\n\n``` js\nvar bufferEqual = require('buffer-equal')\n```\n\nbufferEqual(a, b)\n-----------------\n\nReturn whether the two buffers `a` and `b` are equal.\n\nIf `a` or `b` is not a buffer, return `undefined`.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install buffer-equal\n```\n\nlicense\n=======\n\nMIT\n", + "readmeFilename": "README.markdown", "_id": "buffer-equal@0.0.0", "_from": "buffer-equal@~0.0.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/package.json index dced37e..79f7498 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/package.json @@ -33,6 +33,7 @@ "node": ">=0.4" }, "readme": "deep-equal\n==========\n\nNode's `assert.deepEqual() algorithm` as a standalone module.\n\nexample\n=======\n\n``` js\nvar equal = require('deep-equal');\nconsole.dir([\n equal(\n { a : [ 2, 3 ], b : [ 4 ] },\n { a : [ 2, 3 ], b : [ 4 ] }\n ),\n equal(\n { x : 5, y : [6] },\n { x : 5, y : 6 }\n )\n]);\n```\n\nmethods\n=======\n\nvar deepEqual = require('deep-equal')\n\ndeepEqual(a, b)\n---------------\n\nCompare objects `a` and `b`, returning whether they are equal according to a\nrecursive equality algorithm.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install deep-equal\n```\n\ntest\n====\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm test\n```\n\nlicense\n=======\n\nMIT. Derived largely from node's assert module.\n", + "readmeFilename": "README.markdown", "_id": "deep-equal@0.0.0", "_from": "deep-equal@~0.0.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/index.js index 7a32ca9..cc32f2b 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/index.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/index.js @@ -184,9 +184,9 @@ function difflet (opts, prev, next) { } else write(node.inspect()); } - else if (typeof node == 'object') { + else if (typeof node == 'object' && node !== null) { var insertedKey = false; - var deleted = insertable && prevNode && typeof prevNode === 'object' + var deleted = insertable && typeof prevNode === 'object' && prevNode ? Object.keys(prevNode).filter(function (key) { return !Object.hasOwnProperty.call(node, key); }) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/package.json index 457f70f..33f56af 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/package.json @@ -32,6 +32,7 @@ "node": ">=0.4" }, "readme": "charm\n=====\n\nUse\n[ansi terminal characters](http://www.termsys.demon.co.uk/vtansi.htm)\nto write colors and cursor positions.\n\n![me lucky charms](http://substack.net/images/charms.png)\n\nexample\n=======\n\nlucky\n-----\n\n````javascript\nvar charm = require('charm')(process);\ncharm.reset();\n\nvar colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ];\nvar text = 'Always after me lucky charms.';\n\nvar offset = 0;\nvar iv = setInterval(function () {\n var y = 0, dy = 1;\n for (var i = 0; i < 40; i++) {\n var color = colors[(i + offset) % colors.length];\n var c = text[(i + offset) % text.length];\n charm\n .move(1, dy)\n .foreground(color)\n .write(c)\n ;\n y += dy;\n if (y <= 0 || y >= 5) dy *= -1;\n }\n charm.position(0, 1);\n offset ++;\n}, 150);\n \ncharm.on('data', function (buf) {\n if (buf[0] === 3) {\n clearInterval(iv);\n charm.destroy();\n }\n});\n````\n\nevents\n======\n\nCharm objects pass along the data events from their input stream except for\nevents generated from querying the terminal device.\n\nBecause charm puts stdin into raw mode, charm emits two special events: \"^C\" and\n\"^D\" when the user types those combos. It's super convenient with these events\nto do:\n\n````javascript\ncharm.on('^C', process.exit)\n````\n\nmethods\n=======\n\nvar charm = require('charm')(param or stream, ...)\n--------------------------------------------------\n\nCreate a new `charm` given a `param` with `stdout` and `stdin` streams, such as\n`process` or by passing the streams in themselves separately as parameters.\n\nProtip: you can pass in an http response object as an output stream and it will\njust work™.\n\ncharm.reset()\n-------------\n\nReset the entire screen, like the /usr/bin/reset command.\n\ncharm.destroy()\n---------------\n\nDestroy the input stream.\n\ncharm.write(msg)\n----------------\n\nPass along `msg` to the output stream.\n\ncharm.position(x, y) or charm.position(cb)\n------------------------------------------\n\nSet the cursor position to the absolute coordinates `x, y` or query the position\nand get the response as `cb(x, y)`.\n\ncharm.move(x, y)\n----------------\n\nMove the cursor position by the relative coordinates `x, y`.\n\ncharm.up(y)\n-----------\n\nMove the cursor up by `y` rows.\n\ncharm.down(y)\n-------------\n\nMove the cursor down by `y` rows.\n\ncharm.left(x)\n-------------\n\nMove the cursor left by `x` columns.\n\ncharm.right(x)\n-------------\n\nMove the cursor right by `x` columns.\n\ncharm.push(withAttributes=false)\n--------------------------------\n\nPush the cursor state and optionally the attribute state.\n\ncharm.pop(withAttributes=false)\n-------------------------------\n\nPop the cursor state and optionally the attribute state.\n\ncharm.erase(s)\n--------------\n\nErase a region defined by the string `s`.\n\n`s` can be:\n\n* end - erase from the cursor to the end of the line\n* start - erase from the cursor to the start of the line\n* line - erase the current line\n* down - erase everything below the current line\n* up - erase everything above the current line\n* screen - erase the entire screen\n\ncharm.display(attr)\n-------------------\n\nSet the display mode with the string `attr`.\n\n`attr` can be:\n\n* reset\n* bright\n* dim\n* underscore\n* blink\n* reverse\n* hidden\n\ncharm.foreground(color)\n-----------------------\n\nSet the foreground color with the string `color`, which can be:\n\n* red\n* yellow\n* green\n* blue\n* cyan\n* magenta\n* black\n* white\n\nor `color` can be an integer from 0 to 255, inclusive.\n\ncharm.background(color)\n-----------------------\n\nSet the background color with the string `color`, which can be:\n\n* red\n* yellow\n* green\n* blue\n* cyan\n* magenta\n* black\n* white\n\nor `color` can be an integer from 0 to 255, inclusive.\n\ncharm.cursor(visible)\n---------------------\n\nSet the cursor visibility with a boolean `visible`.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n npm install charm\n", + "readmeFilename": "README.markdown", "_id": "charm@0.0.8", "_from": "charm@0.0.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/package.json index ae4d524..def7eb2 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/package.json @@ -39,6 +39,7 @@ "node": ">=0.6" }, "readme": "traverse\n========\n\nTraverse and transform objects by visiting every node on a recursive walk.\n\n[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse)\n\nexamples\n========\n\ntransform negative numbers in-place\n-----------------------------------\n\nnegative.js\n\n````javascript\nvar traverse = require('traverse');\nvar obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];\n\ntraverse(obj).forEach(function (x) {\n if (x < 0) this.update(x + 128);\n});\n\nconsole.dir(obj);\n````\n\nOutput:\n\n [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]\n\ncollect leaf nodes\n------------------\n\nleaves.js\n\n````javascript\nvar traverse = require('traverse');\n\nvar obj = {\n a : [1,2,3],\n b : 4,\n c : [5,6],\n d : { e : [7,8], f : 9 },\n};\n\nvar leaves = traverse(obj).reduce(function (acc, x) {\n if (this.isLeaf) acc.push(x);\n return acc;\n}, []);\n\nconsole.dir(leaves);\n````\n\nOutput:\n\n [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]\n\nscrub circular references\n-------------------------\n\nscrub.js:\n\n````javascript\nvar traverse = require('traverse');\n\nvar obj = { a : 1, b : 2, c : [ 3, 4 ] };\nobj.c.push(obj);\n\nvar scrubbed = traverse(obj).map(function (x) {\n if (this.circular) this.remove()\n});\nconsole.dir(scrubbed);\n````\n\noutput:\n\n { a: 1, b: 2, c: [ 3, 4 ] }\n\nmethods\n=======\n\nEach method that takes an `fn` uses the context documented below in the context\nsection.\n\n.map(fn)\n--------\n\nExecute `fn` for each node in the object and return a new object with the\nresults of the walk. To update nodes in the result use `this.update(value)`.\n\n.forEach(fn)\n------------\n\nExecute `fn` for each node in the object but unlike `.map()`, when\n`this.update()` is called it updates the object in-place.\n\n.reduce(fn, acc)\n----------------\n\nFor each node in the object, perform a\n[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))\nwith the return value of `fn(acc, node)`.\n\nIf `acc` isn't specified, `acc` is set to the root object for the first step\nand the root element is skipped.\n\n.paths()\n--------\n\nReturn an `Array` of every possible non-cyclic path in the object.\nPaths are `Array`s of string keys.\n\n.nodes()\n--------\n\nReturn an `Array` of every node in the object.\n\n.clone()\n--------\n\nCreate a deep clone of the object.\n\n.get(path)\n----------\n\nGet the element at the array `path`.\n\n.set(path, value)\n-----------------\n\nSet the element at the array `path` to `value`.\n\n.has(path)\n----------\n\nReturn whether the element at the array `path` exists.\n\ncontext\n=======\n\nEach method that takes a callback has a context (its `this` object) with these\nattributes:\n\nthis.node\n---------\n\nThe present node on the recursive walk\n\nthis.path\n---------\n\nAn array of string keys from the root to the present node\n\nthis.parent\n-----------\n\nThe context of the node's parent.\nThis is `undefined` for the root node.\n\nthis.key\n--------\n\nThe name of the key of the present node in its parent.\nThis is `undefined` for the root node.\n\nthis.isRoot, this.notRoot\n-------------------------\n\nWhether the present node is the root node\n\nthis.isLeaf, this.notLeaf\n-------------------------\n\nWhether or not the present node is a leaf node (has no children)\n\nthis.level\n----------\n\nDepth of the node within the traversal\n\nthis.circular\n-------------\n\nIf the node equals one of its parents, the `circular` attribute is set to the\ncontext of that parent and the traversal progresses no deeper.\n\nthis.update(value, stopHere=false)\n----------------------------------\n\nSet a new value for the present node.\n\nAll the elements in `value` will be recursively traversed unless `stopHere` is\ntrue.\n\nthis.remove(stopHere=false)\n-------------\n\nRemove the current element from the output. If the node is in an Array it will\nbe spliced off. Otherwise it will be deleted from its parent.\n\nthis.delete(stopHere=false)\n-------------\n\nDelete the current element from its parent in the output. Calls `delete` even on\nArrays.\n\nthis.before(fn)\n---------------\n\nCall this function before any of the children are traversed.\n\nYou can assign into `this.keys` here to traverse in a custom order.\n\nthis.after(fn)\n--------------\n\nCall this function after any of the children are traversed.\n\nthis.pre(fn)\n------------\n\nCall this function before each of the children are traversed.\n\nthis.post(fn)\n-------------\n\nCall this function after each of the children are traversed.\n\n\ninstall\n=======\n\nUsing [npm](http://npmjs.org) do:\n\n $ npm install traverse\n\ntest\n====\n\nUsing [expresso](http://github.com/visionmedia/expresso) do:\n\n $ expresso\n \n 100% wahoo, your stuff is not broken!\n\nin the browser\n==============\n\nUse [browserify](https://github.com/substack/node-browserify) to run traverse in\nthe browser.\n\ntraverse has been tested and works with:\n\n* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0\n* Firefox 3.5\n* Chrome 6.0\n* Opera 10.6\n* Safari 5.0\n", + "readmeFilename": "README.markdown", "_id": "traverse@0.6.3", "_from": "traverse@0.6.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/package.json index 8a2a4b3..2aff0bc 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/package.json @@ -1,7 +1,7 @@ { "name": "difflet", "description": "colorful diffs for javascript objects", - "version": "0.2.2", + "version": "0.2.3", "repository": { "type": "git", "url": "git://github.com/substack/difflet.git" @@ -39,6 +39,7 @@ "url": "http://substack.net" }, "readme": "difflet\n=======\n\nCreate colorful diffs for javascript objects.\n\nexample\n=======\n\nstring.js\n---------\n\n``` js\nvar difflet = require('difflet');\n\nvar s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 });\nprocess.stdout.write(s);\n```\n\noutput:\n\n![colorful output](http://substack.net/images/screenshots/difflet_string.png)\n\ncolors.js\n---------\n\n``` js\nvar diff = require('difflet')({ indent : 2 });\n\nvar prev = {\n yy : 6,\n zz : 5,\n a : [1,2,3],\n fn : 'beep',\n c : { x : 7, z : 3 }\n};\n\nvar next = {\n a : [ 1, 2, \"z\", /beep/, new Buffer(3) ],\n fn : function qqq () {},\n b : [5,6,7],\n c : { x : 8, y : 5 }\n};\n\ndiff(prev, next).pipe(process.stdout);\n```\n\noutput:\n\n![colorful output](http://substack.net/images/screenshots/difflet_colors.png)\n\ngreen for inserts, blue for updates, red for deletes\n\nmethods\n=======\n\nvar difflet = require('difflet')\n\nvar diff = difflet(opts={})\n---------------------------\n\nCreate a difflet from optional options `opts`.\n\nWith `opts.start(type, stream)` and `opts.stop(type, stream)`,\nyou can write custom handlers for all the types of differences:\n`'inserted'`, `'updated'`, and `'deleted'`.\nBy default green is used for insertions, blue for updates, and red for\ndeletions.\n\nIf `opts.indent` is set, output will span multiple lines and `opts.indent`\nspaces will be used for leading whitespace.\n\nIf `opts.comma === 'first'` then commas will be placed at the start of lines.\n\nSetting `opts.comment` to `true` will turn on comments with the previous\ncontents like this:\n\n![object comments](http://substack.net/images/screenshots/difflet_object_comments.png)\n\ndiff(prev, next)\n----------------\n\nReturn a stream with the colorful changes between objects `prev` and `next`.\n\ndiff.compare(prev, next)\n------------------------\n\nReturn a string with the colorful changes between `prev` and `next`.\n\ndifflet.compare(prev, next)\n---------------------------\n\nReturn a string with the colorful changes between `prev` and `next` with the\ndefault options.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install difflet\n```\n\ntest\n====\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm test\n```\n\nlicense\n=======\n\nMIT/X11\n", - "_id": "difflet@0.2.2", + "readmeFilename": "README.markdown", + "_id": "difflet@0.2.3", "_from": "difflet@~0.2.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/t.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/t.js deleted file mode 100644 index 38e6b2d..0000000 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/t.js +++ /dev/null @@ -1,6 +0,0 @@ -var difflet = require('difflet'); -var s = difflet({ indent : 2, comment : true }).compare( - { foo : 'bar', baz : 100 }, - { ofo : 'aba', baz : 100, boo : 'blerg' } -); -console.log(s); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/inherits-old.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/inherits-old.js new file mode 100644 index 0000000..ef39252 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/inherits-old.js @@ -0,0 +1,40 @@ +// This is a less perfect implementation of the inherits function, +// designed to work in cases where ES5 is not available. +// +// Note that it is a bit longer, and doesn't properly deal with +// getter/setters or property descriptor flags (enumerable, etc.) + +module.exports = inheritsOld + +function inheritsOld (c, p, proto) { + function F () { this.constructor = c } + F.prototype = p.prototype + var e = {} + for (var i in c.prototype) if (c.prototype.hasOwnProperty(i)) { + e[i] = c.prototype[i] + } + if (proto) for (var i in proto) if (proto.hasOwnProperty(i)) { + e[i] = proto[i] + } + c.prototype = new F() + for (var i in e) if (e.hasOwnProperty(i)) { + c.prototype[i] = e[i] + } + 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 () {} +// inheritsOld(Child, Parent) +// new Child diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/package.json index 07a75f1..487b6fa 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/package.json @@ -1,25 +1,8 @@ -{ - "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", - "_id": "inherits@1.0.0", - "_from": "inherits@*" -} +{ "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" : "https://github.com/isaacs/inherits" +, "license": { "type": "WTFPL2" } +, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/package.json index 39ad6f3..f79c6a5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/package.json @@ -27,6 +27,7 @@ "node": "*" }, "readme": "mkdirp\n======\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\nexample\n=======\n\npow.js\n------\n var mkdirp = require('mkdirp');\n \n mkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n });\n\nOutput\n pow!\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\nmethods\n=======\n\nvar mkdirp = require('mkdirp');\n\nmkdirp(dir, mode, cb)\n---------------------\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nmkdirp.sync(dir, mode)\n----------------------\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n npm install mkdirp\n\nlicense\n=======\n\nMIT/X11\n", + "readmeFilename": "README.markdown", "_id": "mkdirp@0.3.4", "_from": "mkdirp@~0.3" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/lib/abbrev.js index 037de2d..bee4132 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/lib/abbrev.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -4,8 +4,15 @@ module.exports = exports = abbrev.abbrev = abbrev abbrev.monkeyPatch = monkeyPatch function monkeyPatch () { - Array.prototype.abbrev = function () { return abbrev(this) } - Object.prototype.abbrev = function () { return abbrev(Object.keys(this)) } + 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) { @@ -32,8 +39,7 @@ function abbrev (list) { var curChar = current.charAt(j) nextMatches = nextMatches && curChar === next.charAt(j) prevMatches = prevMatches && curChar === prev.charAt(j) - if (nextMatches || prevMatches) continue - else { + if (!nextMatches && !prevMatches) { j ++ break } @@ -60,19 +66,18 @@ function lexSort (a, b) { if (module === require.main) { var assert = require("assert") - , sys -sys = require("util") +var util = require("util") console.log("running tests") function test (list, expect) { var actual = abbrev(list) assert.deepEqual(actual, expect, - "abbrev("+sys.inspect(list)+") === " + sys.inspect(expect) + "\n"+ - "actual: "+sys.inspect(actual)) + "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(",")+") === " + sys.inspect(expect) + "\n"+ - "actual: "+sys.inspect(actual)) + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) } test([ "ruby", "ruby", "rules", "rules", "rules" ], diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/package.json index 09b485e..3056f1e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/package.json @@ -1,6 +1,6 @@ { "name": "abbrev", - "version": "1.0.3", + "version": "1.0.4", "description": "Like ruby's abbrev module, but in js", "author": { "name": "Isaac Z. Schlueter", @@ -14,7 +14,12 @@ "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", - "_id": "abbrev@1.0.3", + "readmeFilename": "README.md", + "_id": "abbrev@1.0.4", "_from": "abbrev@1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/package.json index 522e7dd..2291a81 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/package.json @@ -26,6 +26,7 @@ "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", "_id": "nopt@2.0.0", "_from": "nopt@~2" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/traverse/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/traverse/package.json index 056833e..c55d2d6 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/traverse/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/traverse/package.json @@ -18,6 +18,7 @@ "test": "expresso" }, "readme": "traverse\n========\n\nTraverse and transform objects by visiting every node on a recursive walk.\n\nexamples\n========\n\ntransform negative numbers in-place\n-----------------------------------\n\nnegative.js\n\n````javascript\nvar traverse = require('traverse');\nvar obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];\n\ntraverse(obj).forEach(function (x) {\n if (x < 0) this.update(x + 128);\n});\n\nconsole.dir(obj);\n````\n\nOutput:\n\n [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]\n\ncollect leaf nodes\n------------------\n\nleaves.js\n\n````javascript\nvar traverse = require('traverse');\n\nvar obj = {\n a : [1,2,3],\n b : 4,\n c : [5,6],\n d : { e : [7,8], f : 9 },\n};\n\nvar leaves = traverse(obj).reduce(function (acc, x) {\n if (this.isLeaf) acc.push(x);\n return acc;\n}, []);\n\nconsole.dir(leaves);\n````\n\nOutput:\n\n [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]\n\nscrub circular references\n-------------------------\n\nscrub.js:\n\n````javascript\nvar traverse = require('traverse');\n\nvar obj = { a : 1, b : 2, c : [ 3, 4 ] };\nobj.c.push(obj);\n\nvar scrubbed = traverse(obj).map(function (x) {\n if (this.circular) this.remove()\n});\nconsole.dir(scrubbed);\n````\n\noutput:\n\n { a: 1, b: 2, c: [ 3, 4 ] }\n\ncontext\n=======\n\nEach method that takes a callback has a context (its `this` object) with these\nattributes:\n\nthis.node\n---------\n\nThe present node on the recursive walk\n\nthis.path\n---------\n\nAn array of string keys from the root to the present node\n\nthis.parent\n-----------\n\nThe context of the node's parent.\nThis is `undefined` for the root node.\n\nthis.key\n--------\n\nThe name of the key of the present node in its parent.\nThis is `undefined` for the root node.\n\nthis.isRoot, this.notRoot\n-------------------------\n\nWhether the present node is the root node\n\nthis.isLeaf, this.notLeaf\n-------------------------\n\nWhether or not the present node is a leaf node (has no children)\n\nthis.level\n----------\n\nDepth of the node within the traversal\n\nthis.circular\n-------------\n\nIf the node equals one of its parents, the `circular` attribute is set to the\ncontext of that parent and the traversal progresses no deeper.\n\nthis.update(value, stopHere=false)\n----------------------------------\n\nSet a new value for the present node.\n\nAll the elements in `value` will be recursively traversed unless `stopHere` is\ntrue.\n\nthis.remove(stopHere=false)\n-------------\n\nRemove the current element from the output. If the node is in an Array it will\nbe spliced off. Otherwise it will be deleted from its parent.\n\nthis.delete(stopHere=false)\n-------------\n\nDelete the current element from its parent in the output. Calls `delete` even on\nArrays.\n\nthis.before(fn)\n---------------\n\nCall this function before any of the children are traversed.\n\nYou can assign into `this.keys` here to traverse in a custom order.\n\nthis.after(fn)\n--------------\n\nCall this function after any of the children are traversed.\n\nthis.pre(fn)\n------------\n\nCall this function before each of the children are traversed.\n\nthis.post(fn)\n-------------\n\nCall this function after each of the children are traversed.\n\nmethods\n=======\n\n.map(fn)\n--------\n\nExecute `fn` for each node in the object and return a new object with the\nresults of the walk. To update nodes in the result use `this.update(value)`.\n\n.forEach(fn)\n------------\n\nExecute `fn` for each node in the object but unlike `.map()`, when\n`this.update()` is called it updates the object in-place.\n\n.reduce(fn, acc)\n----------------\n\nFor each node in the object, perform a\n[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))\nwith the return value of `fn(acc, node)`.\n\nIf `acc` isn't specified, `acc` is set to the root object for the first step\nand the root element is skipped.\n\n.paths()\n--------\n\nReturn an `Array` of every possible non-cyclic path in the object.\nPaths are `Array`s of string keys.\n\n.nodes()\n--------\n\nReturn an `Array` of every node in the object.\n\n.clone()\n--------\n\nCreate a deep clone of the object.\n\ninstall\n=======\n\nUsing [npm](http://npmjs.org) do:\n\n $ npm install traverse\n\ntest\n====\n\nUsing [expresso](http://github.com/visionmedia/expresso) do:\n\n $ expresso\n \n 100% wahoo, your stuff is not broken!\n\nin the browser\n==============\n\nUse [browserify](https://github.com/substack/node-browserify) to run traverse in\nthe browser.\n\ntraverse has been tested and works with:\n\n* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0\n* Firefox 3.5\n* Chrome 6.0\n* Opera 10.6\n* Safari 5.0\n", + "readmeFilename": "README.markdown", "_id": "traverse@0.5.2", "_from": "traverse@~0.5.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/uglify-js/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/uglify-js/package.json index 6a26136..694ece5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/uglify-js/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/uglify-js/package.json @@ -16,6 +16,7 @@ "url": "git@github.com:mishoo/UglifyJS.git" }, "readme": "\n\n\n\nUglifyJS -- a JavaScript parser/compressor/beautifier\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n

UglifyJS – a JavaScript parser/compressor/beautifier

\n\n\n\n\n
\n

1 UglifyJS — a JavaScript parser/compressor/beautifier

\n
\n\n\n

\nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

\n

\nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

\n

\n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

\n

\nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

\n
    \n
  • \nability to re-generate JavaScript code from the AST. Optionally\nindented—you can use this if you want to “beautify” a program that has\nbeen compressed, so that you can inspect the source. But you can also run\nour code generator to print out an AST without any whitespace, so you\nachieve compression as well.\n\n
  • \n
  • \nshorten variable names (usually to single characters). Our mangler will\nanalyze the code and generate proper variable names, depending on scope\nand usage, and is smart enough to deal with globals defined elsewhere, or\nwith eval() calls or with{} statements. In short, if eval() or\nwith{} are used in some scope, then all variables in that scope and any\nvariables in the parent scopes will remain unmangled, and any references\nto such variables remain unmangled as well.\n\n
  • \n
  • \nvarious small optimizations that may lead to faster code but certainly\nlead to smaller code. Where possible, we do the following:\n\n
      \n
    • \nfoo[\"bar\"] ==> foo.bar\n\n
    • \n
    • \nremove block brackets {}\n\n
    • \n
    • \njoin consecutive var declarations:\nvar a = 10; var b = 20; ==> var a=10,b=20;\n\n
    • \n
    • \nresolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\nreplacement if the result occupies less bytes; for example 1/3 would\ntranslate to 0.333333333333, so in this case we don't replace it.\n\n
    • \n
    • \nconsecutive statements in blocks are merged into a sequence; in many\ncases, this leaves blocks with a single statement, so then we can remove\nthe block brackets.\n\n
    • \n
    • \nvarious optimizations for IF statements:\n\n
        \n
      • \nif (foo) bar(); else baz(); ==> foo?bar():baz();\n
      • \n
      • \nif (!foo) bar(); else baz(); ==> foo?baz():bar();\n
      • \n
      • \nif (foo) bar(); ==> foo&&bar();\n
      • \n
      • \nif (!foo) bar(); ==> foo||bar();\n
      • \n
      • \nif (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
      • \n
      • \nif (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
      • \n
      \n
    • \n
    • \nremove some unreachable code and warn about it (code that follows a\nreturn, throw, break or continue statement, except\nfunction/variable declarations).\n\n
    • \n
    • \nact a limited version of a pre-processor (c.f. the pre-processor of\nC/C++) to allow you to safely replace selected global symbols with\nspecified values. When combined with the optimisations above this can\nmake UglifyJS operate slightly more like a compilation process, in\nthat when certain symbols are replaced by constant values, entire code\nblocks may be optimised away as unreachable.\n
    • \n
    \n
  • \n
\n\n\n\n
\n\n
\n

1.1 Unsafe transformations

\n
\n\n\n

\nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

\n\n
\n\n
\n

1.1.1 Calls involving the global Array constructor

\n
\n\n\n

\nThe following transformations occur:\n

\n\n\n\n
new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
\n\n\n\n

\nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

\n

\nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

\n\n\n\n
// case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
\n\n\n\n
\n\n
\n\n
\n

1.1.2 obj.toString() ==> obj+“”

\n
\n\n\n
\n
\n\n
\n\n
\n

1.2 Install (NPM)

\n
\n\n\n

\nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

\n
\n\n
\n\n
\n

1.3 Install latest code from GitHub

\n
\n\n\n\n\n\n
## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
\n\n\n\n
\n\n
\n\n
\n

1.4 Usage

\n
\n\n\n

\nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

\n\n\n\n
uglifyjs [ options... ] [ filename ]\n
\n\n\n\n

\nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

\n

\nSupported options:\n

\n
    \n
  • \n-b or --beautify — output indented code; when passed, additional\noptions control the beautifier:\n\n
      \n
    • \n-i N or --indent N — indentation level (number of spaces)\n\n
    • \n
    • \n-q or --quote-keys — quote keys in literal objects (by default,\nonly keys that cannot be identifier names will be quotes).\n\n
    • \n
    \n
  • \n
  • \n--ascii — pass this argument to encode non-ASCII characters as\n\\uXXXX sequences. By default UglifyJS won't bother to do it and will\noutput Unicode characters instead. (the output is always encoded in UTF8,\nbut if you pass this option you'll only get ASCII).\n\n
  • \n
  • \n-nm or --no-mangle — don't mangle variable names\n\n
  • \n
  • \n-ns or --no-squeeze — don't call ast_squeeze() (which does various\noptimizations that result in smaller, less readable code).\n\n
  • \n
  • \n-mt or --mangle-toplevel — mangle names in the toplevel scope too\n(by default we don't do this).\n\n
  • \n
  • \n--no-seqs — when ast_squeeze() is called (thus, unless you pass\n--no-squeeze) it will reduce consecutive statements in blocks into a\nsequence. For example, \"a = 10; b = 20; foo();\" will be written as\n\"a=10,b=20,foo();\". In various occasions, this allows us to discard the\nblock brackets (since the block becomes a single statement). This is ON\nby default because it seems safe and saves a few hundred bytes on some\nlibs that I tested it on, but pass --no-seqs to disable it.\n\n
  • \n
  • \n--no-dead-code — by default, UglifyJS will remove code that is\nobviously unreachable (code that follows a return, throw, break or\ncontinue statement and is not a function/variable declaration). Pass\nthis option to disable this optimization.\n\n
  • \n
  • \n-nc or --no-copyright — by default, uglifyjs will keep the initial\ncomment tokens in the generated code (assumed to be copyright information\netc.). If you pass this it will discard it.\n\n
  • \n
  • \n-o filename or --output filename — put the result in filename. If\nthis isn't given, the result goes to standard output (or see next one).\n\n
  • \n
  • \n--overwrite — if the code is read from a file (not from STDIN) and you\npass --overwrite then the output will be written in the same file.\n\n
  • \n
  • \n--ast — pass this if you want to get the Abstract Syntax Tree instead\nof JavaScript as output. Useful for debugging or learning more about the\ninternals.\n\n
  • \n
  • \n-v or --verbose — output some notes on STDERR (for now just how long\neach operation takes).\n\n
  • \n
  • \n-d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\nall instances of the specified symbol where used as an identifier\n(except where symbol has properly declared by a var declaration or\nuse as function parameter or similar) with the specified value. This\nargument may be specified multiple times to define multiple\nsymbols - if no value is specified the symbol will be replaced with\nthe value true, or you can specify a numeric value (such as\n1024), a quoted string value (such as =\"object\"= or\n='https://github.com'), or the name of another symbol or keyword (such as =null or document). \nThis allows you, for example, to assign meaningful names to key\nconstant values but discard the symbolic names in the uglified\nversion for brevity/efficiency, or when used wth care, allows\nUglifyJS to operate as a form of conditional compilation\nwhereby defining appropriate values may, by dint of the constant\nfolding and dead code removal features above, remove entire\nsuperfluous code blocks (e.g. completely remove instrumentation or\ntrace code for production use).\nWhere string values are being defined, the handling of quotes are\nlikely to be subject to the specifics of your command shell\nenvironment, so you may need to experiment with quoting styles\ndepending on your platform, or you may find the option\n--define-from-module more suitable for use.\n\n
  • \n
  • \n-define-from-module SOMEMODULE — will load the named module (as\nper the NodeJS require() function) and iterate all the exported\nproperties of the module defining them as symbol names to be defined\n(as if by the --define option) per the name of each property\n(i.e. without the module name prefix) and given the value of the\nproperty. This is a much easier way to handle and document groups of\nsymbols to be defined rather than a large number of --define\noptions.\n\n
  • \n
  • \n--unsafe — enable other additional optimizations that are known to be\nunsafe in some contrived situations, but could still be generally useful.\nFor now only these:\n\n
      \n
    • \nfoo.toString() ==> foo+\"\"\n
    • \n
    • \nnew Array(x,…) ==> [x,…]\n
    • \n
    • \nnew Array(x) ==> Array(x)\n\n
    • \n
    \n
  • \n
  • \n--max-line-len (default 32K characters) — add a newline after around\n32K characters. I've seen both FF and Chrome croak when all the code was\non a single line of around 670K. Pass –max-line-len 0 to disable this\nsafety feature.\n\n
  • \n
  • \n--reserved-names — some libraries rely on certain names to be used, as\npointed out in issue #92 and #81, so this option allow you to exclude such\nnames from the mangler. For example, to keep names require and $super\nintact you'd specify –reserved-names \"require,$super\".\n\n
  • \n
  • \n--inline-script – when you want to include the output literally in an\nHTML <script> tag you can use this option to prevent </script from\nshowing up in the output.\n\n
  • \n
  • \n--lift-vars – when you pass this, UglifyJS will apply the following\ntransformations (see the notes in API, ast_lift_variables):\n\n
      \n
    • \nput all var declarations at the start of the scope\n
    • \n
    • \nmake sure a variable is declared only once\n
    • \n
    • \ndiscard unused function arguments\n
    • \n
    • \ndiscard unused inner (named) functions\n
    • \n
    • \nfinally, try to merge assignments into that one var declaration, if\npossible.\n
    • \n
    \n
  • \n
\n\n\n\n
\n\n
\n

1.4.1 API

\n
\n\n\n

\nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

\n\n\n\n
var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
\n\n\n\n

\nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

\n

\nSome of these functions take optional arguments. Here's a description:\n

\n
    \n
  • \njsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\nstrict_semicolons is optional and defaults to false. If you pass\ntrue then the parser will throw an error when it expects a semicolon and\nit doesn't find it. For most JS code you don't want that, but it's useful\nif you want to strictly sanitize your code.\n\n
  • \n
  • \npro.ast_lift_variables(ast) – merge and move var declarations to the\nscop of the scope; discard unused function arguments or variables; discard\nunused (named) inner functions. It also tries to merge assignments\nfollowing the var declaration into it.\n\n

    \nIf your code is very hand-optimized concerning var declarations, this\nlifting variable declarations might actually increase size. For me it\nhelps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\nnote that (since it's not enabled by default) this operation isn't yet\nheavily tested (please report if you find issues!).\n

    \n

    \nNote that although it might increase the image size (on jQuery it gains\n865 bytes, 243 after gzip) it's technically more correct: in certain\nsituations, dead code removal might drop variable declarations, which\nwould not happen if the variables are lifted in advance.\n

    \n

    \nHere's an example of what it does:\n

    \n
  • \n
\n\n\n\n\n
function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
\n\n\n\n
    \n
  • \npro.ast_mangle(ast, options) – generates a new AST containing mangled\n(compressed) variable and function names. It supports the following\noptions:\n\n
      \n
    • \ntoplevel – mangle toplevel names (by default we don't touch them).\n
    • \n
    • \nexcept – an array of names to exclude from compression.\n
    • \n
    • \ndefines – an object with properties named after symbols to\nreplace (see the --define option for the script) and the values\nrepresenting the AST replacement value.\n\n
    • \n
    \n
  • \n
  • \npro.ast_squeeze(ast, options) – employs further optimizations designed\nto reduce the size of the code that gen_code would generate from the\nAST. Returns a new AST. options can be a hash; the supported options\nare:\n\n
      \n
    • \nmake_seqs (default true) which will cause consecutive statements in a\nblock to be merged using the \"sequence\" (comma) operator\n\n
    • \n
    • \ndead_code (default true) which will remove unreachable code.\n\n
    • \n
    \n
  • \n
  • \npro.gen_code(ast, options) – generates JS code from the AST. By\ndefault it's minified, but using the options argument you can get nicely\nformatted output. options is, well, optional :-) and if you pass it it\nmust be an object and supports the following properties (below you can see\nthe default values):\n\n
      \n
    • \nbeautify: false – pass true if you want indented output\n
    • \n
    • \nindent_start: 0 (only applies when beautify is true) – initial\nindentation in spaces\n
    • \n
    • \nindent_level: 4 (only applies when beautify is true) --\nindentation level, in spaces (pass an even number)\n
    • \n
    • \nquote_keys: false – if you pass true it will quote all keys in\nliteral objects\n
    • \n
    • \nspace_colon: false (only applies when beautify is true) – wether\nto put a space before the colon in object literals\n
    • \n
    • \nascii_only: false – pass true if you want to encode non-ASCII\ncharacters as \\uXXXX.\n
    • \n
    • \ninline_script: false – pass true to escape occurrences of\n</script in strings\n
    • \n
    \n
  • \n
\n\n\n
\n\n
\n\n
\n

1.4.2 Beautifier shortcoming – no more comments

\n
\n\n\n

\nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

\n

\nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

\n
\n\n
\n\n
\n

1.4.3 Use as a code pre-processor

\n
\n\n\n

\nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

\n

\nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

\n\n\n\n
CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
\n\n\n\n

\nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

\n

\nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

\n

\nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

\n

\nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

\n

\nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

\n
\n
\n\n
\n\n
\n

1.5 Compression – how good is it?

\n
\n\n\n

\nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

\n

\nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
\n\n\n
\n\n
\n\n
\n

1.6 Bugs?

\n
\n\n\n

\nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

\n

\nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

\n

\nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

\n
\n\n
\n\n
\n

1.7 Links

\n
\n\n\n\n\n\n
\n\n
\n\n
\n

1.8 License

\n
\n\n\n

\nUglifyJS is released under the BSD license:\n

\n\n\n\n
Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
\n\n\n\n\n
\n
\n
\n
\n

Footnotes:

\n
\n

1 I even reported a few bugs and suggested some fixes in the original\nparse-js library, and Marijn pushed fixes literally in minutes.\n

\n
\n
\n
\n

Author: Mihai Bazon\n

\n

Date: 2011-08-29 19:17:55 EEST

\n

HTML generated by org-mode 7.01trans in emacs 23

\n
\n
\n\n\n", + "readmeFilename": "README.html", "_id": "uglify-js@1.1.1", "_from": "uglify-js@~1.1.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/package.json index 38f64f0..48510d5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/package.json @@ -41,6 +41,7 @@ "url": "http://substack.net" }, "readme": "burrito\n=======\n\nBurrito makes it easy to do crazy stuff with the javascript AST.\n\nThis is super useful if you want to roll your own stack traces or build a code\ncoverage tool.\n\n[![build status](https://secure.travis-ci.org/substack/node-burrito.png)](http://travis-ci.org/substack/node-burrito)\n\n![node.wrap(\"burrito\")](http://substack.net/images/burrito.png)\n\nexamples\n========\n\nmicrowave\n---------\n\nexamples/microwave.js\n\n````javascript\nvar burrito = require('burrito');\n\nvar res = burrito.microwave('Math.sin(2)', function (node) {\n if (node.name === 'num') node.wrap('Math.PI / %s');\n});\n\nconsole.log(res); // sin(pi / 2) == 1\n````\n\noutput:\n\n 1\n\nwrap\n----\n\nexamples/wrap.js\n\n````javascript\nvar burrito = require('burrito');\n\nvar src = burrito('f() && g(h())\\nfoo()', function (node) {\n if (node.name === 'call') node.wrap('qqq(%s)');\n});\n\nconsole.log(src);\n````\n\noutput:\n\n qqq(f()) && qqq(g(qqq(h())));\n\n qqq(foo());\n\nmethods\n=======\n\n var burrito = require('burrito');\n\nburrito(code, cb)\n-----------------\n\nGiven some source `code` and a function `trace`, walk the ast by expression.\n\nThe `cb` gets called with a node object described below.\n\nIf `code` is an Array then it is assumbed to be an AST which you can generate\nyourself with `burrito.parse()`. The AST must be annotated, so make sure to\n`burrito.parse(src, false, true)`.\n\nburrito.microwave(code, context={}, cb)\n---------------------------------------\n\nLike `burrito()` except the result is run using\n`vm.runInNewContext(res, context)`.\n\nnode object\n===========\n\nnode.name\n---------\n\nName is a string that contains the type of the expression as named by uglify.\n\nnode.wrap(s)\n------------\n\nWrap the current expression in `s`.\n\nIf `s` is a string, `\"%s\"` will be replaced with the stringified current\nexpression.\n\nIf `s` is a function, it is called with the stringified current expression and\nshould return a new stringified expression.\n\nIf the `node.name === \"binary\"`, you get the subterms \"%a\" and \"%b\" to play with\ntoo. These subterms are applied if `s` is a function too: `s(expr, a, b)`.\n\nProtip: to insert multiple statements you can use javascript's lesser-known block\nsyntax that it gets from C:\n\n````javascript\nif (node.name === 'stat') node.wrap('{ foo(); %s }')\n````\n\nnode.node\n---------\n\nraw ast data generated by uglify\n\nnode.value\n----------\n\n`node.node.slice(1)` to skip the annotations\n\nnode.start\n----------\n\nThe start location of the expression, like this:\n\n````javascript\n{ type: 'name',\n value: 'b',\n line: 0,\n col: 3,\n pos: 3,\n nlb: false,\n comments_before: [] }\n````\n\nnode.end\n--------\n\nThe end location of the expression, formatted the same as `node.start`.\n\nnode.state\n----------\n\nThe state of the traversal using traverse.\n\nnode.source()\n-------------\n\nReturns a stringified version of the expression.\n\nnode.parent()\n-------------\n\nReturns the parent `node` or `null` if the node is the root element.\n\nnode.label()\n------------\n\nReturn the label of the present node or `null` if there is no label.\n\nLabels are returned for \"call\", \"var\", \"defun\", and \"function\" nodes.\n\nReturns an array for \"var\" nodes since `var` statements can\ncontain multiple labels in assignment.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) you can just:\n\n npm install burrito\n\nin the browser\n==============\n\nBurrito works in browser with\n[browserify](https://github.com/substack/node-browserify).\n\nIt has been tested against:\n\n* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0\n* Firefox 3.5\n* Chrome 6.0\n* Opera 10.6\n* Safari 5.0\n\nkudos\n=====\n\nHeavily inspired by (and previously mostly lifted outright from) isaacs's nifty\ntmp/instrument.js thingy from uglify-js.\n", + "readmeFilename": "README.markdown", "_id": "burrito@0.2.12", "_from": "burrito@>=0.2.5 <0.3" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/package.json index d118a1f..b03ceea 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/package.json @@ -35,6 +35,7 @@ "node": ">=0.4" }, "readme": "bunker\n======\n\nBunker is a module to calculate code coverage using native javascript\n[burrito](https://github.com/substack/node-burrito) AST trickery.\n\n[![build status](https://secure.travis-ci.org/substack/node-bunker.png)](http://travis-ci.org/substack/node-bunker)\n\n![code coverage](http://substack.net/images/code_coverage.png)\n\nexamples\n========\n\ntiny\n----\n\n````javascript\nvar bunker = require('bunker');\nvar b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }');\n\nvar counts = {};\n\nb.on('node', function (node) {\n if (!counts[node.id]) {\n counts[node.id] = { times : 0, node : node };\n }\n counts[node.id].times ++;\n});\n\nb.run();\n\nObject.keys(counts).forEach(function (key) {\n var count = counts[key];\n console.log(count.times + ' : ' + count.node.source());\n});\n````\n\noutput:\n\n $ node example/tiny.js \n 1 : var x=0;\n 31 : i<30\n 30 : i++\n 30 : x++;\n 30 : x++\n\nmethods\n=======\n\nvar bunker = require('bunker');\n\nvar b = bunker(src)\n-------------------\n\nCreate a new bunker code coverageifier with some source `src`.\n\nThe bunker object `b` is an `EventEmitter` that emits `'node'` events with two\nparameters:\n\n* `node` - the [burrito](https://github.com/substack/node-burrito) node object\n* `stack` - the stack, [stackedy](https://github.com/substack/node-stackedy) style\n\nb.include(src)\n--------------\n\nInclude some source into the bunker.\n\nb.compile()\n-----------\n\nReturn the source wrapped with burrito.\n\nb.assign(context={})\n--------------------\n\nAssign the statement-tracking functions into `context`.\n\nb.run(context={})\n-----------------\n\nRun the source using `vm.runInNewContext()` with some `context`.\nThe statement-tracking functions will be added to `context` by `assign()`.\n", + "readmeFilename": "README.markdown", "_id": "bunker@0.1.2", "_from": "bunker@0.1.X" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/package.json index cd7eb05..66cc184 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/package.json @@ -32,6 +32,7 @@ "node": ">=0.4" }, "readme": "runforcover\n======\n\nRunforcover is a require-hook library that uses node-bunker to provide code coverage data\nfor your unit test library, whatever it might be.\n\nmethods\n=======\nvar runforcover = require('runforcover');\n\nvar coverage = runforcover.cover([RegExp | path]);\n-------\n\nAttach runforcover to the global `require` object and patch `require.extensions['.js']` to\nprovide coverage metadata for all files required after this point. Returns a function\nobject that can be called to obtain a object keying files to `CoverageData` objects, with \na method for releasing control back to vanilla `require`. Usage:\n\n````javascript\n\nvar coverage = runforcover.cover(/.*/g);\n\nrequire('some/library');\n\ncoverage(function(coverageData) {\n // coverageData is an object keyed by filename.\n var stats = coverageData['/full/path/to/file.js'].stats()\n\n // the percentage of lines run versus total lines in file\n console.log(stats.percentage);\n\n // the number of missing lines\n console.log(stats.missing);\n\n // the number of lines run (seen)\n console.log(stats.seen);\n\n // an array of line objects representing 'missed' lines\n stats.lines;\n\n stats.lines.forEach(function(line) {\n // the line number of the line:\n console.log(line.number);\n\n // returns a string containing the source data for the line:\n console.log(line.source()); \n }); \n \n // return control back to the original require function\n coverage.release(); \n});\n````\n\nlicense\n=======\nnew BSD.\n", + "readmeFilename": "README.markdown", "_id": "runforcover@0.0.2", "_from": "runforcover@~0.0.2" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/package.json index 30210e5..9c46b9a 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/package.json @@ -25,6 +25,7 @@ "url": "git://github.com/isaacs/slide-flow-control.git" }, "readme": "# Slide - a tiny flow control library\n\nCallbacks are simple and easy if you keep the pattern consistent.\n\nCheck out the [slide presentation](http://github.com/isaacs/slide-flow-control/raw/master/nodejs-controlling-flow.pdf).\n\nYou'll laugh when you see how little code is actually in this thing.\nIt's so not-enterprisey, you won't believe it. It does almost nothing,\nbut it's super handy.\n\nI actually use an earlier version of this util in\n[a real world program](http://npmjs.org/).\n\n## Installation\n\nJust copy the files into your project, and use them that way, or\nyou can do this:\n\n npm install slide\n\nand then:\n\n var asyncMap = require(\"slide\").asyncMap\n , chain = require(\"slide\").chain\n // use the power!\n\nEnjoy!\n", + "readmeFilename": "README.md", "_id": "slide@1.1.3", "_from": "slide@*" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/package.json index 25f560b..359300d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/package.json @@ -1,30 +1,9 @@ -{ - "name": "yamlish", - "description": "Parser/encoder for the yamlish format", - "repository": { - "type": "git", - "url": "https://github.com/isaacs/yamlish" - }, - "version": "0.0.5", - "main": "yamlish.js", - "keywords": [ - "yaml", - "yamlish", - "test", - "anything", - "protocol", - "tap" - ], - "license": { - "type": "MIT", - "url": "http://github.com/isaacs/yamlish/raw/master/LICENSE" - }, - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "readme": "This is a thingie to parse the \"yamlish\" format used to serialize\nobjects in the TAP format.\n\nIt's like yaml, but just a tiny little bit smaller.\n\nUsage:\n\n var yamlish = require(\"yamlish\")\n // returns a string like:\n /*\n some:\n object:\n - full\n - of\n pretty: things\n */\n yamlish.encode({some:{object:[\"full\", \"of\"]}, pretty:\"things\"})\n\n // returns the object\n yamlish.decode(someYamlishString)\n", - "_id": "yamlish@0.0.5", - "_from": "yamlish@*" -} +{ "name" : "yamlish" +, "description" : "Parser/encoder for the yamlish format" +, "repository":"https://github.com/isaacs/yamlish" +, "version" : "0.0.5" +, "main" : "yamlish.js" +, "keywords" : [ "yaml", "yamlish", "test", "anything", "protocol", "tap"] +, "license" : { "type" : "MIT" + , "url" : "http://github.com/isaacs/yamlish/raw/master/LICENSE" } +, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/package.json index 4489a15..f0d48d0 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/package.json @@ -1,6 +1,6 @@ { "name": "tap", - "version": "0.3.1", + "version": "0.3.3", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", @@ -49,8 +49,9 @@ "scripts": { "test": "bin/tap.js test/*.js" }, - "readme": "This is a mix-and-match set of utilities that you can use to write test\nharnesses and frameworks that communicate with one another using the\nTest Anything Protocol.\n\nIf you don't yet know what TAP is, [you better ask\nsomebody](http://testanything.org/).\n\nDefault Usage:\n\n1. Make a directory. Maybe call it 'test'. That'd be nice and obvious.\n2. Put a bunch of test scripts in there. If they're node programs, then\n they should be \".js\". Anything else is assumed to be some kind of shell\n script, which should have a shebang line.\n3. `npm install tap`\n4. `tap ./tests`\n\nThe output will be TAP-compliant.\n\nFor extra special bonus points, you can do something like this:\n\n var test = require(\"tap\").test\n test(\"make sure the thingie is a thing\", function (t) {\n t.equal(thingie, \"thing\", \"thingie should be thing\")\n t.type(thingie, \"string\", \"type of thingie is string\")\n t.ok(true, \"this is always true\")\n t.notOk(false, \"this is never true\")\n t.test(\"a child test\", function (t) {\n t.equal(this, superEasy, \"right!?\")\n t.similar(7, 2, \"ever notice 7 is kinda like 2?\", {todo: true})\n t.test(\"so skippable\", {skip: true}, function (t) {\n t.plan(1) // only one test in this block\n t.ok(true, \"but when the flag changes, it'll pass\")\n // no need to end, since we had a plan.\n })\n t.end()\n })\n t.ok(99, \"can also skip individual assertions\", {skip: true})\n // end lets it know it's over.\n t.end()\n })\n test(\"another one\", function (t) {\n t.plan(1)\n t.ok(true, \"It's ok to plan, and also end. Watch.\")\n t.end() // but it must match the plan!\n })\n\nNode-tap is actually a collection of several modules, any of which may be\nmixed and matched however you please.\n\nIf you don't like this test framework, and think you can do much much\nbetter, *I strongly encourage you to do so!* If you use this library,\nhowever, at least to output TAP-compliant results when `process.env.TAP`\nis set, then the data coming out of your framework will be much more\nconsumable by machines.\n\nYou can also use this to build programs that *consume* the TAP data, so\nthis is very useful for CI systems and such.\n\n* tap-assert: A collection of assert functions that return TAP result\n objects.\n* tap-consumer: A stream interface for consuming TAP data.\n* tap-producer: A class that produces a TAP stream by taking in result\n objects.\n* tap-results: A class for keeping track of TAP result objects as they\n pass by, counting up skips, passes, fails, and so on.\n* tap-runner: A program that runs through a directory running all the\n tests in it. (Tests which may or may not be TAP-outputting tests. But\n it's better if they are.)\n* tap-test: A class for actually running tests.\n* tap-harness: A class that runs tests. (Tests are also Harnesses,\n which is how sub-tests run.)\n* tap-global-harness: A default harness that provides the top-level\n support for running TAP tests.\n\n## Experimental Code Coverage with runforcover & bunker:\n\n```\nTAP_COV=1 tap ./tests [--cover=./lib,foo.js] [--cover-dir=./coverage]\n```\n\nThis feature is experimental, and will most likely change somewhat\nbefore being finalized. Feedback welcome.\n", - "_id": "tap@0.3.1", + "readme": "This is a mix-and-match set of utilities that you can use to write test\nharnesses and frameworks that communicate with one another using the\nTest Anything Protocol.\n\nIf you don't yet know what TAP is, [you better ask\nsomebody](http://testanything.org/).\n\nDefault Usage:\n\n1. Make a directory. Maybe call it 'test'. That'd be nice and obvious.\n2. Put a bunch of test scripts in there. If they're node programs, then\n they should be \".js\". Anything else is assumed to be some kind of shell\n script, which should have a shebang line.\n3. `npm install tap`\n4. `tap ./test`\n\nThe output will be TAP-compliant.\n\nFor extra special bonus points, you can do something like this:\n\n var test = require(\"tap\").test\n test(\"make sure the thingie is a thing\", function (t) {\n t.equal(thingie, \"thing\", \"thingie should be thing\")\n t.type(thingie, \"string\", \"type of thingie is string\")\n t.ok(true, \"this is always true\")\n t.notOk(false, \"this is never true\")\n t.test(\"a child test\", function (t) {\n t.equal(this, superEasy, \"right!?\")\n t.similar(7, 2, \"ever notice 7 is kinda like 2?\", {todo: true})\n t.test(\"so skippable\", {skip: true}, function (t) {\n t.plan(1) // only one test in this block\n t.ok(true, \"but when the flag changes, it'll pass\")\n // no need to end, since we had a plan.\n })\n t.end()\n })\n t.ok(99, \"can also skip individual assertions\", {skip: true})\n // end lets it know it's over.\n t.end()\n })\n test(\"another one\", function (t) {\n t.plan(1)\n t.ok(true, \"It's ok to plan, and also end. Watch.\")\n t.end() // but it must match the plan!\n })\n\nNode-tap is actually a collection of several modules, any of which may be\nmixed and matched however you please.\n\nIf you don't like this test framework, and think you can do much much\nbetter, *I strongly encourage you to do so!* If you use this library,\nhowever, at least to output TAP-compliant results when `process.env.TAP`\nis set, then the data coming out of your framework will be much more\nconsumable by machines.\n\nYou can also use this to build programs that *consume* the TAP data, so\nthis is very useful for CI systems and such.\n\n* tap-assert: A collection of assert functions that return TAP result\n objects.\n* tap-consumer: A stream interface for consuming TAP data.\n* tap-producer: A class that produces a TAP stream by taking in result\n objects.\n* tap-results: A class for keeping track of TAP result objects as they\n pass by, counting up skips, passes, fails, and so on.\n* tap-runner: A program that runs through a directory running all the\n tests in it. (Tests which may or may not be TAP-outputting tests. But\n it's better if they are.)\n* tap-test: A class for actually running tests.\n* tap-harness: A class that runs tests. (Tests are also Harnesses,\n which is how sub-tests run.)\n* tap-global-harness: A default harness that provides the top-level\n support for running TAP tests.\n\n## Experimental Code Coverage with runforcover & bunker:\n\n```\nTAP_COV=1 tap ./test [--cover=./lib,foo.js] [--cover-dir=./coverage]\n```\n\nThis feature is experimental, and will most likely change somewhat\nbefore being finalized. Feedback welcome.\n", + "readmeFilename": "README.md", + "_id": "tap@0.3.3", "bundleDependencies": [ "inherits", "tap-consumer", diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/output-childtest-description.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/output-childtest-description.js new file mode 100644 index 0000000..e025ba8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/output-childtest-description.js @@ -0,0 +1,50 @@ +var tap = require("../") + , fs = require("fs") + , path = require('path') + , cp = require("child_process") + , nestedTests = + [ "var test = require('..').test" + , "test('parent test description', function (t) {" + , " t.plan(2)" + , " t.ok(true, 'test in parent')" + , " t.test('child test description', function (t) {" + , " t.plan(1)" + , " t.ok(true, 'test in child') " + , " })" + , "})" + ].join("\n") + , nestedTestsFile = path.join(__dirname, "nested-tests-fixture.js") + +fs.writeFileSync(nestedTestsFile, nestedTests, "utf8") +console.log(nestedTestsFile); + +tap.test("nested tests, parent and child pass", function (t) { + /* + * Ensure the output includes the following lines in the right order: + * '# parent test description' + * 'ok 1 test in parent' + * '# child test description' + * 'ok 2 test in child' + */ + + t.plan(5) + + cp.exec("node " + nestedTestsFile, function (err, stdo, stde) { + var lines = stdo.split("\n") + , parentDes = lines.indexOf("# parent test description") + , parentRes = lines.indexOf("ok 1 test in parent") + , childDes = lines.indexOf("# child test description") + , childRes = lines.indexOf("ok 2 test in child") + + t.notEqual(parentDes, -1, "outputs parent description") + t.notEqual(childDes, -1, "outputs child description") + + t.ok(parentDes < parentRes , "outputs parent description before parent result") + t.ok(parentRes < childDes , "outputs parent result before child description") + t.ok(childDes < childRes , "outputs child description before child result") + + fs.unlinkSync(nestedTestsFile); + t.end() + }) +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/undefined_indented.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/undefined_indented.js new file mode 100644 index 0000000..98abe02 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/undefined_indented.js @@ -0,0 +1,27 @@ +var tap = require("../") + +tap.test("consume yaml", function (t) { + t.plan(1) + + var s = + [ "not ok 1 beep boop" + , " ---" + , " stack:" + , " - rawr" + , " - dinosaurs" + , " ..." + ].join("\n") + , c = tap.createConsumer() + + c.on("data", function (res) { + t.same(res, { + id: 1 + , ok: false + , name: " beep boop" // <-- should perhaps .trim() this? + , stack: [ "rawr", "dinosaurs" ] + }) + t.end() + }) + c.write(s) + c.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/package.json index bb6afa3..a2ea6c3 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/package.json @@ -87,10 +87,11 @@ "dependencies": { "tap": ">=0.2.3" }, + "readme": "Nodeunit\n========\n\nSimple syntax, powerful tools. Nodeunit provides easy async unit testing for\nnode.js and the browser.\n\n* Simple to use\n* Just export the tests from a module\n* Works with node.js and in the browser.\n* Helps you avoid common pitfalls when testing asynchronous code\n* Easy to add test cases with setUp and tearDown functions if you wish\n* Flexible reporters for custom output, built-in support for HTML and jUnit XML\n* Allows the use of mocks and stubs\n\n__Contributors__\n\n* [alexgorbatchev](https://github.com/alexgorbatchev)\n* [alexkwolfe](https://github.com/alexkwolfe)\n* [azatoth](https://github.com/azatoth)\n* [kadirpekel](https://github.com/kadirpekel)\n* [lambdalisue](https://github.com/lambdalisue)\n* [luebken](https://github.com/luebken)\n* [orlandov](https://github.com/orlandov)\n* [Sannis](https://github.com/Sannis)\n* [sstephenson](https://github.com/sstephenson)\n* [thegreatape](https://github.com/thegreatape)\n* [mmalecki](https://github.com/mmalecki)\n* and thanks to [cjohansen](https://github.com/cjohansen) for input and advice\n on implementing setUp and tearDown functions. See\n [cjohansen's fork](https://github.com/cjohansen/nodeunit).\n\nAlso, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl)\nproject, which implements a 'pretty dsl on top of nodeunit'.\n\nMore contributor information can be found in the\n[CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md)\nfile.\n\nUsage\n-----\n\nHere is an example unit test module:\n\n exports.testSomething = function(test){\n test.expect(1);\n test.ok(true, \"this assertion should pass\");\n test.done();\n };\n\n exports.testSomethingElse = function(test){\n test.ok(false, \"this assertion should fail\");\n test.done();\n };\n\nWhen run using the included test runner, this will output the following:\n\n\n\nInstallation\n------------\n\nThere are two options for installing nodeunit:\n\n1. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit),\n then:\n\n make && sudo make install\n\n2. Install via npm:\n\n npm install nodeunit\n\nAPI Documentation\n-----------------\n\nNodeunit uses the functions available in the node.js\n[assert module](http://nodejs.org/docs/v0.4.2/api/assert.html):\n\n* __ok(value, [message])__ - Tests if value is a true value.\n* __equal(actual, expected, [message])__ - Tests shallow, coercive equality\n with the equal comparison operator ( == ).\n* __notEqual(actual, expected, [message])__ - Tests shallow, coercive\n non-equality with the not equal comparison operator ( != ).\n* __deepEqual(actual, expected, [message])__ - Tests for deep equality.\n* __notDeepEqual(actual, expected, [message])__ - Tests for any deep\n inequality.\n* __strictEqual(actual, expected, [message])__ - Tests strict equality, as\n determined by the strict equality operator ( === )\n* __notStrictEqual(actual, expected, [message])__ - Tests strict non-equality,\n as determined by the strict not equal operator ( !== )\n* __throws(block, [error], [message])__ - Expects block to throw an error.\n* __doesNotThrow(block, [error], [message])__ - Expects block not to throw an\n error.\n* __ifError(value)__ - Tests if value is not a false value, throws if it is a\n true value. Useful when testing the first argument, error in callbacks.\n\nNodeunit also provides the following functions within tests:\n\n* __expect(amount)__ - Specify how many assertions are expected to run within a\n test. Very useful for ensuring that all your callbacks and assertions are\n run.\n* __done()__ - Finish the current test function, and move on to the next. ALL\n tests should call this!\n\nNodeunit aims to be simple and easy to learn. This is achieved through using\nexisting structures (such as node.js modules) to maximum effect, and reducing\nthe API where possible, to make it easier to digest.\n\nTests are simply exported from a module, but they are still run in the order\nthey are defined.\n\n__Note:__ Users of old nodeunit versions may remember using ok, equals and same\nin the style of qunit, instead of the assert functions above. These functions\nstill exist for backwards compatibility, and are simply aliases to their assert\nmodule counterparts.\n\n\nAsynchronous Testing\n--------------------\n\nWhen testing asynchronous code, there are a number of sharp edges to watch out\nfor. Thankfully, nodeunit is designed to help you avoid as many of these\npitfalls as possible. For the most part, testing asynchronous code in nodeunit\n_just works_.\n\n\n### Tests run in series\n\nWhile running tests in parallel seems like a good idea for speeding up your\ntest suite, in practice I've found it means writing much more complicated\ntests. Because of node's module cache, running tests in parallel means mocking\nand stubbing is pretty much impossible. One of the nicest things about testing\nin javascript is the ease of doing stubs:\n\n var _readFile = fs.readFile;\n fs.readFile = function(path, callback){\n // its a stub!\n };\n // test function that uses fs.readFile\n\n // we're done\n fs.readFile = _readFile;\n\nYou cannot do this when running tests in parallel. In order to keep testing as\nsimple as possible, nodeunit avoids it. Thankfully, most unit-test suites run\nfast anyway.\n\n\n### Explicit ending of tests\n\nWhen testing async code its important that tests end at the correct point, not\njust after a given number of assertions. Otherwise your tests can run short,\nending before all assertions have completed. Its important to detect too\nmany assertions as well as too few. Combining explicit ending of tests with\nan expected number of assertions helps to avoid false test passes, so be sure\nto use the test.expect() method at the start of your test functions, and\ntest.done() when finished.\n\n\nGroups, setUp and tearDown\n--------------------------\n\nNodeunit allows the nesting of test functions:\n\n exports.test1 = function (test) {\n ...\n }\n\n exports.group = {\n test2: function (test) {\n ...\n },\n test3: function (test) {\n ...\n }\n }\n\nThis would be run as:\n\n test1\n group - test2\n group - test3\n\nUsing these groups, Nodeunit allows you to define a `setUp` function, which is\nrun before each test, and a `tearDown` function, which is run after each test\ncalls `test.done()`:\n\n module.exports = {\n setUp: function (callback) {\n this.foo = 'bar';\n callback();\n },\n tearDown: function (callback) {\n // clean up\n callback();\n },\n test1: function (test) {\n test.equals(this.foo, 'bar');\n test.done();\n }\n };\n\nIn this way, its possible to have multiple groups of tests in a module, each\ngroup with its own setUp and tearDown functions.\n\n\nRunning Tests\n-------------\n\nNodeunit comes with a basic command-line test runner, which can be installed\nusing 'sudo make install'. Example usage:\n\n nodeunit testmodule1.js testfolder [...]\n\nThe default test reporter uses color output, because I think that's more fun :) I\nintend to add a no-color option in future. To give you a feeling of the fun you'll\nbe having writing tests, lets fix the example at the start of the README:\n\n\n\nAhhh, Doesn't that feel better?\n\nWhen using the included test runner, it will exit using the failed number of\nassertions as the exit code. Exiting with 0 when all tests pass.\n\n\n### Command-line Options\n\n* __--reporter FILE__ - you can set the test reporter to a custom module or\non of the modules in nodeunit/lib/reporters, when omitted, the default test runner\nis used.\n* __--list-reporters__ - list available build-in reporters.\n* __--config FILE__ - load config options from a JSON file, allows\nthe customisation of color schemes for the default test reporter etc. See\nbin/nodeunit.json for current available options.\n* __--version__ or __-v__ - report nodeunit version\n* __--help__ - show nodeunit help\n\n\nRunning tests in the browser\n----------------------------\n\nNodeunit tests can also be run inside the browser. For example usage, see\nthe examples/browser folder. The basic syntax is as follows:\n\n__test.html__\n\n \n \n Example Test Suite\n \n \n \n \n \n \n

Example Test Suite

\n \n \n \n\nHere, suite1 and suite2 are just object literals containing test functions or\ngroups, as would be returned if you did require('test-suite') in node.js:\n\n__suite1.js__\n\n this.suite1 = {\n 'example test': function (test) {\n test.ok(true, 'everything is ok');\n test.done();\n }\n };\n\nIf you wish to use a commonjs format for your test suites (using exports), it is\nup to you to define the commonjs tools for the browser. There are a number of\nalternatives and its important it fits with your existing code, which is\nwhy nodeunit does not currently provide this out of the box.\n\nIn the example above, the tests will run when the page is loaded.\n\nThe browser-version of nodeunit.js is created in dist/browser when you do, 'make\nbrowser'. You'll need [UglifyJS](https://github.com/mishoo/UglifyJS) installed in\norder for it to automatically create nodeunit.min.js.\n\n\nAdding nodeunit to Your Projects\n--------------------------------\n\nIf you don't want people to have to install the nodeunit command-line tool,\nyou'll want to create a script that runs the tests for your project with the\ncorrect require paths set up. Here's an example test script, that assumes you\nhave nodeunit in a suitably located node_modules directory.\n\n #!/usr/bin/env node\n var reporter = require('nodeunit').reporters.default;\n reporter.run(['test']);\n\nIf you're using git, you might find it useful to include nodeunit as a\nsubmodule. Using submodules makes it easy for developers to download nodeunit\nand run your test suite, without cluttering up your repository with\nthe source code. To add nodeunit as a git submodule do the following:\n\n git submodule add git://github.com/caolan/nodeunit.git node_modules/nodeunit\n\nThis will add nodeunit to the node_modules folder of your project. Now, when\ncloning the repository, nodeunit can be downloaded by doing the following:\n\n git submodule init\n git submodule update\n\nLet's update the test script above with a helpful hint on how to get nodeunit,\nif its missing:\n\n #!/usr/bin/env node\n try {\n var reporter = require('nodeunit').reporters.default;\n }\n catch(e) {\n console.log(\"Cannot find nodeunit module.\");\n console.log(\"You can download submodules for this project by doing:\");\n console.log(\"\");\n console.log(\" git submodule init\");\n console.log(\" git submodule update\");\n console.log(\"\");\n process.exit();\n }\n\n process.chdir(__dirname);\n reporter.run(['test']);\n\nNow if someone attempts to run your test suite without nodeunit installed they\nwill be prompted to download the submodules for your project.\n\n\nBuilt-in Test Reporters\n-----------------------\n\n* __default__ - The standard reporter seen in the nodeunit screenshots\n* __minimal__ - Pretty, minimal output, shows errors and progress only\n* __html__ - Outputs a HTML report to stdout\n* __junit__ - Creates jUnit compatible XML reports, which can be used with\n continuous integration tools such as [Hudson](http://hudson-ci.org/).\n* __machineout__ - Simple reporter for machine analysis. There is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim)\n which is useful for TDD on VIM\n\n\nWriting a Test Reporter\n---------------------\n\nNodeunit exports runTest(fn, options), runModule(mod, options) and\nrunFiles(paths, options). You'll most likely want to run test suites from\nfiles, which can be done using the latter function. The _options_ argument can\ncontain callbacks which run during testing. Nodeunit provides the following\ncallbacks:\n\n* __moduleStart(name)__ - called before a module is tested\n* __moduleDone(name, assertions)__ - called once all test functions within the\n module have completed (see assertions object reference below)\n ALL tests within the module\n* __testStart(name)__ - called before a test function is run\n* __testDone(name, assertions)__ - called once a test function has completed\n (by calling test.done())\n* __log(assertion)__ - called whenever an assertion is made (see assertion\n object reference below)\n* __done(assertions)__ - called after all tests/modules are complete\n\nThe __assertion__ object:\n\n* __passed()__ - did the assertion pass?\n* __failed()__ - did the assertion fail?\n* __error__ - the AssertionError if the assertion failed\n* __method__ - the nodeunit assertion method used (ok, same, equals...)\n* __message__ - the message the assertion method was called with (optional)\n\nThe __assertionList__ object:\n\n* An array-like object with the following new attributes:\n * __failures()__ - the number of assertions which failed\n * __duration__ - the time taken for the test to complete in msecs\n\nFor a reference implementation of a test reporter, see lib/reporters/default.js in\nthe nodeunit project directory.\n\n\nSandbox utility\n---------------\n\nThis is a function which evaluates JavaScript files in a sandbox and returns the\ncontext. The sandbox function can be used for testing client-side code or private\nun-exported functions within a module.\n\n var sandbox = require('nodeunit').utils.sandbox;\n var example = sandbox('example.js');\n\n__sandbox(files, sandbox)__ - Evaluates JavaScript files in a sandbox, returning\nthe context. The first argument can either be a single filename or an array of\nfilenames. If multiple filenames are given their contents are concatenated before\nevalution. The second argument is an optional context to use for the sandbox.\n\n\nRunning the nodeunit Tests\n--------------------------\n\nThe tests for nodeunit are written using nodeunit itself as the test framework.\nHowever, the module test-base.js first does some basic tests using the assert\nmodule to ensure that test functions are actually run, and a basic level of\nnodeunit functionality is available.\n\nTo run the nodeunit tests do:\n\n make test\n\n__Note:__ There was a bug in node v0.2.0 causing the tests to hang, upgrading\nto v0.2.1 fixes this.\n\n\n__machineout__ reporter\n----------------------------------------------\n\nThe default reporter is really readable for human but for machinally analysis. \nWhen you want to analyze the output of nodeunit, use __machineout__ reporter and you will get\n\n\n\n\nnodeunit with vim\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nThere is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) so you can use nodeunit with VIM.\nThat compiler use __machineout__ reporter and it is useful to use with [vim-makegreen](https://github.com/reinh/vim-makegreen)\n\n \n\nContributing\n------------\n\nContributions to the project are most welcome, so feel free to fork and improve.\nWhen submitting a pull request, please run 'make lint' first to ensure\nwe're following a consistent coding style.\n", + "readmeFilename": "README.md", "man": [ "/Users/fredwu/.npm/nodeunit/0.7.4/package/man1/nodeunit.1" ], - "readme": "Nodeunit\n========\n\nSimple syntax, powerful tools. Nodeunit provides easy async unit testing for\nnode.js and the browser.\n\n* Simple to use\n* Just export the tests from a module\n* Works with node.js and in the browser.\n* Helps you avoid common pitfalls when testing asynchronous code\n* Easy to add test cases with setUp and tearDown functions if you wish\n* Flexible reporters for custom output, built-in support for HTML and jUnit XML\n* Allows the use of mocks and stubs\n\n__Contributors__\n\n* [alexgorbatchev](https://github.com/alexgorbatchev)\n* [alexkwolfe](https://github.com/alexkwolfe)\n* [azatoth](https://github.com/azatoth)\n* [kadirpekel](https://github.com/kadirpekel)\n* [lambdalisue](https://github.com/lambdalisue)\n* [luebken](https://github.com/luebken)\n* [orlandov](https://github.com/orlandov)\n* [Sannis](https://github.com/Sannis)\n* [sstephenson](https://github.com/sstephenson)\n* [thegreatape](https://github.com/thegreatape)\n* [mmalecki](https://github.com/mmalecki)\n* and thanks to [cjohansen](https://github.com/cjohansen) for input and advice\n on implementing setUp and tearDown functions. See\n [cjohansen's fork](https://github.com/cjohansen/nodeunit).\n\nAlso, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl)\nproject, which implements a 'pretty dsl on top of nodeunit'.\n\nMore contributor information can be found in the\n[CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md)\nfile.\n\nUsage\n-----\n\nHere is an example unit test module:\n\n exports.testSomething = function(test){\n test.expect(1);\n test.ok(true, \"this assertion should pass\");\n test.done();\n };\n\n exports.testSomethingElse = function(test){\n test.ok(false, \"this assertion should fail\");\n test.done();\n };\n\nWhen run using the included test runner, this will output the following:\n\n\n\nInstallation\n------------\n\nThere are two options for installing nodeunit:\n\n1. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit),\n then:\n\n make && sudo make install\n\n2. Install via npm:\n\n npm install nodeunit\n\nAPI Documentation\n-----------------\n\nNodeunit uses the functions available in the node.js\n[assert module](http://nodejs.org/docs/v0.4.2/api/assert.html):\n\n* __ok(value, [message])__ - Tests if value is a true value.\n* __equal(actual, expected, [message])__ - Tests shallow, coercive equality\n with the equal comparison operator ( == ).\n* __notEqual(actual, expected, [message])__ - Tests shallow, coercive\n non-equality with the not equal comparison operator ( != ).\n* __deepEqual(actual, expected, [message])__ - Tests for deep equality.\n* __notDeepEqual(actual, expected, [message])__ - Tests for any deep\n inequality.\n* __strictEqual(actual, expected, [message])__ - Tests strict equality, as\n determined by the strict equality operator ( === )\n* __notStrictEqual(actual, expected, [message])__ - Tests strict non-equality,\n as determined by the strict not equal operator ( !== )\n* __throws(block, [error], [message])__ - Expects block to throw an error.\n* __doesNotThrow(block, [error], [message])__ - Expects block not to throw an\n error.\n* __ifError(value)__ - Tests if value is not a false value, throws if it is a\n true value. Useful when testing the first argument, error in callbacks.\n\nNodeunit also provides the following functions within tests:\n\n* __expect(amount)__ - Specify how many assertions are expected to run within a\n test. Very useful for ensuring that all your callbacks and assertions are\n run.\n* __done()__ - Finish the current test function, and move on to the next. ALL\n tests should call this!\n\nNodeunit aims to be simple and easy to learn. This is achieved through using\nexisting structures (such as node.js modules) to maximum effect, and reducing\nthe API where possible, to make it easier to digest.\n\nTests are simply exported from a module, but they are still run in the order\nthey are defined.\n\n__Note:__ Users of old nodeunit versions may remember using ok, equals and same\nin the style of qunit, instead of the assert functions above. These functions\nstill exist for backwards compatibility, and are simply aliases to their assert\nmodule counterparts.\n\n\nAsynchronous Testing\n--------------------\n\nWhen testing asynchronous code, there are a number of sharp edges to watch out\nfor. Thankfully, nodeunit is designed to help you avoid as many of these\npitfalls as possible. For the most part, testing asynchronous code in nodeunit\n_just works_.\n\n\n### Tests run in series\n\nWhile running tests in parallel seems like a good idea for speeding up your\ntest suite, in practice I've found it means writing much more complicated\ntests. Because of node's module cache, running tests in parallel means mocking\nand stubbing is pretty much impossible. One of the nicest things about testing\nin javascript is the ease of doing stubs:\n\n var _readFile = fs.readFile;\n fs.readFile = function(path, callback){\n // its a stub!\n };\n // test function that uses fs.readFile\n\n // we're done\n fs.readFile = _readFile;\n\nYou cannot do this when running tests in parallel. In order to keep testing as\nsimple as possible, nodeunit avoids it. Thankfully, most unit-test suites run\nfast anyway.\n\n\n### Explicit ending of tests\n\nWhen testing async code its important that tests end at the correct point, not\njust after a given number of assertions. Otherwise your tests can run short,\nending before all assertions have completed. Its important to detect too\nmany assertions as well as too few. Combining explicit ending of tests with\nan expected number of assertions helps to avoid false test passes, so be sure\nto use the test.expect() method at the start of your test functions, and\ntest.done() when finished.\n\n\nGroups, setUp and tearDown\n--------------------------\n\nNodeunit allows the nesting of test functions:\n\n exports.test1 = function (test) {\n ...\n }\n\n exports.group = {\n test2: function (test) {\n ...\n },\n test3: function (test) {\n ...\n }\n }\n\nThis would be run as:\n\n test1\n group - test2\n group - test3\n\nUsing these groups, Nodeunit allows you to define a `setUp` function, which is\nrun before each test, and a `tearDown` function, which is run after each test\ncalls `test.done()`:\n\n module.exports = {\n setUp: function (callback) {\n this.foo = 'bar';\n callback();\n },\n tearDown: function (callback) {\n // clean up\n callback();\n },\n test1: function (test) {\n test.equals(this.foo, 'bar');\n test.done();\n }\n };\n\nIn this way, its possible to have multiple groups of tests in a module, each\ngroup with its own setUp and tearDown functions.\n\n\nRunning Tests\n-------------\n\nNodeunit comes with a basic command-line test runner, which can be installed\nusing 'sudo make install'. Example usage:\n\n nodeunit testmodule1.js testfolder [...]\n\nThe default test reporter uses color output, because I think that's more fun :) I\nintend to add a no-color option in future. To give you a feeling of the fun you'll\nbe having writing tests, lets fix the example at the start of the README:\n\n\n\nAhhh, Doesn't that feel better?\n\nWhen using the included test runner, it will exit using the failed number of\nassertions as the exit code. Exiting with 0 when all tests pass.\n\n\n### Command-line Options\n\n* __--reporter FILE__ - you can set the test reporter to a custom module or\non of the modules in nodeunit/lib/reporters, when omitted, the default test runner\nis used.\n* __--list-reporters__ - list available build-in reporters.\n* __--config FILE__ - load config options from a JSON file, allows\nthe customisation of color schemes for the default test reporter etc. See\nbin/nodeunit.json for current available options.\n* __--version__ or __-v__ - report nodeunit version\n* __--help__ - show nodeunit help\n\n\nRunning tests in the browser\n----------------------------\n\nNodeunit tests can also be run inside the browser. For example usage, see\nthe examples/browser folder. The basic syntax is as follows:\n\n__test.html__\n\n \n \n Example Test Suite\n \n \n \n \n \n \n

Example Test Suite

\n \n \n \n\nHere, suite1 and suite2 are just object literals containing test functions or\ngroups, as would be returned if you did require('test-suite') in node.js:\n\n__suite1.js__\n\n this.suite1 = {\n 'example test': function (test) {\n test.ok(true, 'everything is ok');\n test.done();\n }\n };\n\nIf you wish to use a commonjs format for your test suites (using exports), it is\nup to you to define the commonjs tools for the browser. There are a number of\nalternatives and its important it fits with your existing code, which is\nwhy nodeunit does not currently provide this out of the box.\n\nIn the example above, the tests will run when the page is loaded.\n\nThe browser-version of nodeunit.js is created in dist/browser when you do, 'make\nbrowser'. You'll need [UglifyJS](https://github.com/mishoo/UglifyJS) installed in\norder for it to automatically create nodeunit.min.js.\n\n\nAdding nodeunit to Your Projects\n--------------------------------\n\nIf you don't want people to have to install the nodeunit command-line tool,\nyou'll want to create a script that runs the tests for your project with the\ncorrect require paths set up. Here's an example test script, that assumes you\nhave nodeunit in a suitably located node_modules directory.\n\n #!/usr/bin/env node\n var reporter = require('nodeunit').reporters.default;\n reporter.run(['test']);\n\nIf you're using git, you might find it useful to include nodeunit as a\nsubmodule. Using submodules makes it easy for developers to download nodeunit\nand run your test suite, without cluttering up your repository with\nthe source code. To add nodeunit as a git submodule do the following:\n\n git submodule add git://github.com/caolan/nodeunit.git node_modules/nodeunit\n\nThis will add nodeunit to the node_modules folder of your project. Now, when\ncloning the repository, nodeunit can be downloaded by doing the following:\n\n git submodule init\n git submodule update\n\nLet's update the test script above with a helpful hint on how to get nodeunit,\nif its missing:\n\n #!/usr/bin/env node\n try {\n var reporter = require('nodeunit').reporters.default;\n }\n catch(e) {\n console.log(\"Cannot find nodeunit module.\");\n console.log(\"You can download submodules for this project by doing:\");\n console.log(\"\");\n console.log(\" git submodule init\");\n console.log(\" git submodule update\");\n console.log(\"\");\n process.exit();\n }\n\n process.chdir(__dirname);\n reporter.run(['test']);\n\nNow if someone attempts to run your test suite without nodeunit installed they\nwill be prompted to download the submodules for your project.\n\n\nBuilt-in Test Reporters\n-----------------------\n\n* __default__ - The standard reporter seen in the nodeunit screenshots\n* __minimal__ - Pretty, minimal output, shows errors and progress only\n* __html__ - Outputs a HTML report to stdout\n* __junit__ - Creates jUnit compatible XML reports, which can be used with\n continuous integration tools such as [Hudson](http://hudson-ci.org/).\n* __machineout__ - Simple reporter for machine analysis. There is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim)\n which is useful for TDD on VIM\n\n\nWriting a Test Reporter\n---------------------\n\nNodeunit exports runTest(fn, options), runModule(mod, options) and\nrunFiles(paths, options). You'll most likely want to run test suites from\nfiles, which can be done using the latter function. The _options_ argument can\ncontain callbacks which run during testing. Nodeunit provides the following\ncallbacks:\n\n* __moduleStart(name)__ - called before a module is tested\n* __moduleDone(name, assertions)__ - called once all test functions within the\n module have completed (see assertions object reference below)\n ALL tests within the module\n* __testStart(name)__ - called before a test function is run\n* __testDone(name, assertions)__ - called once a test function has completed\n (by calling test.done())\n* __log(assertion)__ - called whenever an assertion is made (see assertion\n object reference below)\n* __done(assertions)__ - called after all tests/modules are complete\n\nThe __assertion__ object:\n\n* __passed()__ - did the assertion pass?\n* __failed()__ - did the assertion fail?\n* __error__ - the AssertionError if the assertion failed\n* __method__ - the nodeunit assertion method used (ok, same, equals...)\n* __message__ - the message the assertion method was called with (optional)\n\nThe __assertionList__ object:\n\n* An array-like object with the following new attributes:\n * __failures()__ - the number of assertions which failed\n * __duration__ - the time taken for the test to complete in msecs\n\nFor a reference implementation of a test reporter, see lib/reporters/default.js in\nthe nodeunit project directory.\n\n\nSandbox utility\n---------------\n\nThis is a function which evaluates JavaScript files in a sandbox and returns the\ncontext. The sandbox function can be used for testing client-side code or private\nun-exported functions within a module.\n\n var sandbox = require('nodeunit').utils.sandbox;\n var example = sandbox('example.js');\n\n__sandbox(files, sandbox)__ - Evaluates JavaScript files in a sandbox, returning\nthe context. The first argument can either be a single filename or an array of\nfilenames. If multiple filenames are given their contents are concatenated before\nevalution. The second argument is an optional context to use for the sandbox.\n\n\nRunning the nodeunit Tests\n--------------------------\n\nThe tests for nodeunit are written using nodeunit itself as the test framework.\nHowever, the module test-base.js first does some basic tests using the assert\nmodule to ensure that test functions are actually run, and a basic level of\nnodeunit functionality is available.\n\nTo run the nodeunit tests do:\n\n make test\n\n__Note:__ There was a bug in node v0.2.0 causing the tests to hang, upgrading\nto v0.2.1 fixes this.\n\n\n__machineout__ reporter\n----------------------------------------------\n\nThe default reporter is really readable for human but for machinally analysis. \nWhen you want to analyze the output of nodeunit, use __machineout__ reporter and you will get\n\n\n\n\nnodeunit with vim\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nThere is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) so you can use nodeunit with VIM.\nThat compiler use __machineout__ reporter and it is useful to use with [vim-makegreen](https://github.com/reinh/vim-makegreen)\n\n \n\nContributing\n------------\n\nContributions to the project are most welcome, so feel free to fork and improve.\nWhen submitting a pull request, please run 'make lint' first to ensure\nwe're following a consistent coding style.\n", "_id": "nodeunit@0.7.4", "_from": "nodeunit@~0.7.4" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/LICENSE @@ -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. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js index 037de2d..bee4132 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -4,8 +4,15 @@ module.exports = exports = abbrev.abbrev = abbrev abbrev.monkeyPatch = monkeyPatch function monkeyPatch () { - Array.prototype.abbrev = function () { return abbrev(this) } - Object.prototype.abbrev = function () { return abbrev(Object.keys(this)) } + 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) { @@ -32,8 +39,7 @@ function abbrev (list) { var curChar = current.charAt(j) nextMatches = nextMatches && curChar === next.charAt(j) prevMatches = prevMatches && curChar === prev.charAt(j) - if (nextMatches || prevMatches) continue - else { + if (!nextMatches && !prevMatches) { j ++ break } @@ -60,19 +66,18 @@ function lexSort (a, b) { if (module === require.main) { var assert = require("assert") - , sys -sys = require("util") +var util = require("util") console.log("running tests") function test (list, expect) { var actual = abbrev(list) assert.deepEqual(actual, expect, - "abbrev("+sys.inspect(list)+") === " + sys.inspect(expect) + "\n"+ - "actual: "+sys.inspect(actual)) + "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(",")+") === " + sys.inspect(expect) + "\n"+ - "actual: "+sys.inspect(actual)) + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) } test([ "ruby", "ruby", "rules", "rules", "rules" ], diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json index 09b485e..3056f1e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json @@ -1,6 +1,6 @@ { "name": "abbrev", - "version": "1.0.3", + "version": "1.0.4", "description": "Like ruby's abbrev module, but in js", "author": { "name": "Isaac Z. Schlueter", @@ -14,7 +14,12 @@ "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", - "_id": "abbrev@1.0.3", + "readmeFilename": "README.md", + "_id": "abbrev@1.0.4", "_from": "abbrev@1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/package.json index 4ae4747..6d4bc5e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/package.json @@ -26,6 +26,7 @@ "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.\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", "_id": "nopt@1.0.10", "_from": "nopt@~1.0.10" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/package.json index c281c54..9f3cb69 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/package.json @@ -26,6 +26,7 @@ "node": ">= 0.4.0" }, "readme": "# node-pkginfo\n\nAn easy way to expose properties on a module from a package.json\n\n## Installation\n\n### Installing npm (node package manager)\n```\n curl http://npmjs.org/install.sh | sh\n```\n\n### Installing pkginfo\n```\n [sudo] npm install pkginfo\n```\n\n## Motivation\nHow often when writing node.js modules have you written the following line(s) of code? \n\n* Hard code your version string into your code\n\n``` js\n exports.version = '0.1.0';\n```\n\n* Programmatically expose the version from the package.json\n\n``` js\n exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;\n```\n\nIn other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**\n\n## Usage\n\nUsing `pkginfo` is idiot-proof, just require and invoke it. \n\n``` js\n var pkginfo = require('pkginfo')(module);\n \n console.dir(module.exports);\n```\n\nBy invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). \n\nHere's a sample of the output:\n\n```\n { name: 'simple-app',\n description: 'A test fixture for pkginfo',\n version: '0.1.0',\n author: 'Charlie Robbins ',\n keywords: [ 'test', 'fixture' ],\n main: './index.js',\n scripts: { test: 'vows test/*-test.js --spec' },\n engines: { node: '>= 0.4.0' } }\n```\n\n### Expose specific properties\nIf you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:\n\n``` js\n var pkginfo = require('pkginfo')(module, 'version', 'author');\n \n console.dir(module.exports);\n```\n\n```\n { version: '0.1.0',\n author: 'Charlie Robbins ' }\n```\n\nIf you're looking for further usage see the [examples][0] included in this repository. \n\n## Run Tests\nTests are written in [vows][1] and give complete coverage of all APIs.\n\n```\n vows test/*-test.js --spec\n```\n\n[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples\n[1]: http://vowsjs.org\n\n#### Author: [Charlie Robbins](http://nodejitsu.com)", + "readmeFilename": "README.md", "_id": "pkginfo@0.2.3", "_from": "pkginfo@0.x.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/package.json index bcbefe0..4f3d459 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/package.json @@ -34,6 +34,7 @@ "node": "> 0.1.90" }, "readme": "eyes\n====\n\na customizable value inspector for Node.js\n\nsynopsis\n--------\n\nI was tired of looking at cluttered output in the console -- something needed to be done,\n`sys.inspect()` didn't display regexps correctly, and was too verbose, and I had an hour or two to spare. \nSo I decided to have some fun. _eyes_ were born.\n\n![eyes-ss](http://dl.dropbox.com/u/251849/eyes-js-ss.gif)\n\n_example of the output of a user-customized eyes.js inspector_\n\n*eyes* also deals with circular objects in an intelligent way, and can pretty-print object literals.\n\nusage\n-----\n\n var inspect = require('eyes').inspector({styles: {all: 'magenta'}});\n\n inspect(something); // inspect with the settings passed to `inspector`\n\nor\n\n var eyes = require('eyes');\n\n eyes.inspect(something); // inspect with the default settings\n\nyou can pass a _label_ to `inspect()`, to keep track of your inspections:\n\n eyes.inspect(something, \"a random value\");\n\nIf you want to return the output of eyes without printing it, you can set it up this way:\n\n var inspect = require('eyes').inspector({ stream: null });\n\n sys.puts(inspect({ something: 42 }));\n\ncustomization\n-------------\n\nThese are the default styles and settings used by _eyes_.\n\n styles: { // Styles applied to stdout\n all: 'cyan', // Overall style applied to everything\n label: 'underline', // Inspection labels, like 'array' in `array: [1, 2, 3]`\n other: 'inverted', // Objects which don't have a literal representation, such as functions\n key: 'bold', // The keys in object literals, like 'a' in `{a: 1}`\n special: 'grey', // null, undefined...\n string: 'green',\n number: 'magenta',\n bool: 'blue', // true false\n regexp: 'green', // /\\d+/\n },\n \n pretty: true, // Indent object literals\n hideFunctions: false, // Don't output functions at all\n stream: process.stdout, // Stream to write to, or null\n maxLength: 2048 // Truncate output if longer\n\nYou can overwrite them with your own, by passing a similar object to `inspector()` or `inspect()`.\n\n var inspect = require('eyes').inspector({\n styles: {\n all: 'magenta',\n special: 'bold'\n },\n maxLength: 512\n });\n\n", + "readmeFilename": "README.md", "_id": "eyes@0.1.8", "_from": "eyes@0.1.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/package.json index d35a944..c13b2ef 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/package.json @@ -27,6 +27,7 @@ "test": "node tests/run.js" }, "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n
\n  npm install request\n
\n\nOr from source:\n\n
\n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n
\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\n\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Assume by some stretch of magic you aquired the verifier\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: VERIFIER\n , token_secret: access_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n", + "readmeFilename": "README.md", "_id": "request@2.9.203", "_from": "request@2.9.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/package.json index c630d72..5fb2082 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/package.json @@ -33,6 +33,7 @@ "node": ">= 0.2.0" }, "readme": "# timespan\n\nA simple implementation of TimeSpans in Javascript.\n\n## Installation in node.js\n\n### Installing npm (node package manager)\n``` bash\n $ curl http://npmjs.org/install.sh | sh\n```\n\n### Installing timespan\n``` bash\n [sudo] npm install timespan\n```\n\n## Usage \nYou have two options when creating a new TimeSpan object: either explicitly instantiate it using the TimeSpan constructor function or use a helper method to create from a specific length of time.\n\n### Using the new constructor\n\n``` js\n var timespan = require('timespan');\n var ts = new timespan.TimeSpan();\n```\n\nThe constructor takes 5 parameters, all which are optional and which can be used to initialize the TimeSpan to a given value. These parameters are: `milliseconds`, `seconds`, `minutes`, `hours`, `days`.\n\n``` js\n //\n // Initializes the TimeSpan to 4 Minutes, 16 Seconds and 0 Milliseconds.\n //\n var ts = new TimeSpan(0,16,4)\n\n //\n // Initializes the TimeSpan to 3 hours, 4 minutes, 10 seconds and 0 msecs.\n //\n var ts = new TimeSpan(0,10,64,2);\n```\n\n### Using Construction Helper Method(s) \nYou can initialize a new TimeSpan by calling one of these Functions:\n\n``` js\n timespan.FromSeconds(/* seconds */);\n timespan.FromMinutes(/* minutes */);\n timespan.FromHours(/* hours */);\n timespan.FromDays(/* hours */);\n \n //\n // This behaves differently, see below\n //\n timespan.FromDates(start, end);\n```\n\nThe first four helper methods take a single numeric parameter and create a new TimeSpan instance. e.g. `timespan.FromSeconds(45)` is equivalent to `new TimeSpan(0,45)`. If the parameter is invalid/not a number, it will just be treated as 0 no error will be thrown.\n\n`timespan.FromDates()` is different as it takes two dates. The TimeSpan will be the difference between these dates.\n\nIf the second date is earlier than the first date, the TimeSpan will have a negative value. You can pass in \"true\" as the third parameter to force the TimeSpan to be positive always.\n\n``` js\n var date1 = new Date(2010, 3, 1, 10, 10, 5, 0);\n var date2 = new Date(2010, 3, 1, 10, 10, 10, 0);\n var ts = TimeSpan.FromDates(date2, date1);\n var ts2 = TimeSpan.FromDates(date2, date1, true);\n \n //\n // -5, because we put the later date first\n //\n console.log(ts.totalSeconds()); \n \n //\n // 5, because we passed true as third parameter\n //\n console.log(ts2.totalSeconds()); \n```\n\n\n### Adding / Subtracting TimeSpans\nThere are several functions to add or subtract time:\n\n``` js\n ts.addMilliseconds()\n ts.addSeconds()\n ts.addMinutes()\n ts.addHours()\n ts.addDays()\n ts.subtractMilliseconds()\n ts.subtractSeconds()\n ts.subtractMinutes()\n ts.subtractHours()\n ts.subtractDays()\n```\n\nAll these functions take a single numeric parameter. If the parameter is invalid, not a number, or missing it will be ignored and no Error is thrown.\n\n``` js\n var ts = new TimeSpan();\n ts.addSeconds(30);\n ts.addMinutes(2);\n ts.subtractSeconds(60);\n \n //\n // ts will now be a timespan of 1 minute and 30 seconds\n //\n```\n\nThe parameter can be negative to negate the operation `ts.addSeconds(-30)` is equivalent to `ts.subtractSeconds(30)`.\n\n### Interacting with Other TimeSpan instances\nThese are the functions that interact with another TimeSpan:\n\n``` js\n ts.add()\n ts.subtract()\n ts.equals()\n```\n\nadd and subtract add/subtract the other TimeSpan to the current one:\n\n``` js\n var ts = TimeSpan.FromSeconds(30);\n var ts2 = TimeSpan.FromMinutes(2);\n ts.add(ts2);\n \n //\n // ts is now a TimeSpan of 2 Minutes, 30 Seconds\n // ts2 is unchanged\n //\n```\n\nequals checks if two TimeSpans have the same time:\n\n``` js\n var ts = TimeSpan.FromSeconds(30);\n var ts2 = TimeSpan.FromSeconds(30);\n var eq = ts.equals(ts2); // true\n ts2.addSeconds(1);\n var eq2 = ts.equals(ts2); // false\n```\n\n### Retrieving the Value of a TimeSpan\nThere are two sets of functions to retreive the function of the TimeSpan: those that deal with the full value in various measurements and another that gets the individual components.\n\n#### Retrieve the full value\n\n``` js\n ts.totalMilliseconds()\n ts.totalSeconds()\n ts.totalMinutes()\n ts.totalHours()\n ts.totalDays()\n```\n\nThese functions convert the value to the given format and return it. The result can be a floating point number. These functions take a single parameter roundDown which can be set to true to round the value down to an Integer.\n\n``` js\n var ts = TimeSpan.fromSeconds(90);\n console.log(ts.totalMilliseconds()); // 90000\n console.log(ts.totalSeconds()); // 90\n console.log(ts.totalMinutes()); // 1.5\n console.log(ts.totalMinutes(true)); // 1\n```\n\n#### Retrieve a component of the TimeSpan\n\n``` js\n ts.milliseconds\n ts.seconds\n ts.minutes\n ts.hours\n ts.days\n```\n\nThese functions return a component of the TimeSpan that could be used to represent a clock. \n\n``` js\n var ts = TimeSpan.FromSeconds(90);\n console.log(ts.seconds()); // 30\n console.log(ts.minutes()); // 1\n```\n\nBasically these value never \"overflow\" - seconds will only return 0 to 59, hours only 0 to 23 etc. Days could grow infinitely. All of these functions automatically round down the result:\n\n``` js\n var ts = TimeSpan.FromDays(2);\n ts.addHours(12);\n console.log(ts.days()); // 2\n console.log(ts.hours()); // 12\n```\n\n## Remark about Backwards Compatibility\nVersion 0.2.x was designed to work with [node.js][0] and backwards compatibility to the browser-based usage was not considered a high priority. This will be fixed in future versions, but for now if you need to use this in the browser, you can find the 0.1.x code under `/browser`.\n\n#### Author: [Michael Stum](http://www.stum.de)\n#### Contributors: [Charlie Robbins](http://github.com/indexzero)\n\n[0]: http://nodejs.org ", + "readmeFilename": "README.md", "_id": "timespan@2.2.0", "_from": "timespan@2.x.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/package.json index 23762b1..31aee25 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/package.json @@ -49,6 +49,7 @@ "node": ">= 0.4.0" }, "readme": "# node-loggly\n\nA client implementation for Loggly in node.js\n\n## Installation\n\n### Installing npm (node package manager)\n``` bash\n $ curl http://npmjs.org/install.sh | sh\n```\n\n### Installing node-loggly\n``` bash\n $ [sudo] npm install loggly\n```\n\n## Usage\n\nThe node-loggly library is compliant with the [Loggly API][0]. Using node-loggly is easy for a variety of scenarios: logging, working with devices and inputs, searching, and facet searching.\n\n### Getting Started\nBefore we can do anything with Loggly, we have to create a client with valid credentials. We will authenticate for you automatically: \n\n``` js\n var loggly = require('loggly');\n var config = {\n subdomain: \"your-subdomain\",\n auth: {\n username: \"your-username\",\n password: \"your-password\"\n }\n };\n var client = loggly.createClient(config);\n```\n\n### Logging\nThere are two ways to send log information to Loggly via node-loggly. The first is to simply call client.log with an appropriate input token:\n\n``` js\n client.log('your-really-long-input-token', '127.0.0.1 - Theres no place like home', function (err, result) {\n // Do something once you've logged\n });\n```\n\nNote that the callback in the above example is optional, if you prefer the 'fire and forget' method of logging:\n\n``` js\n client.log('your-really-long-input-token', '127.0.0.1 - Theres no place like home');\n```\n\nThe second way to send log information to Loggly is to do so once you've retrieved an input directly from Loggly:\n\n``` js\n client.getInput('your-input-name', function (err, input) {\n input.log('127.0.0.1 - Theres no place like home');\n });\n```\n\nAgain the callback in the above example is optional and you can pass it if you'd like to.\n\n### Logging Shallow JSON Object Literals as a String\nIn addition to logging pure strings it is also possible to pass shallow JSON object literals (i.e. no nested objects) to client.log(..) or input.log(..) methods, which will get converted into the [Loggly recommended string representation][1]. So\n\n``` js\n var source = {\n foo: 1,\n bar: 2,\n buzz: 3\n };\n \n input.log(source);\n```\n\nwill be logged as: \n\n```\n foo=1,bar=2,buzz=3\n```\n\n### Logging Objects to JSON Enabled Loggly Inputs\nIt is also possible to log complex objects using the new JSON capabilities of Loggly. To enable JSON functionality in the client simply add 'json: true' to the configuration:\n\n``` js\n var config = {\n subdomain: \"your-subdomain\",\n auth: {\n username: \"your-username\",\n password: \"your-password\"\n },\n json: true\n };\n```\n\nWhen the json flag is enabled, objects will be converted to JSON using JSON.stringify before being transmitted to Loggly. So\n\n``` js\n var source = {\n foo: 1,\n bar: 2,\n buzz: {\n sheep: 'jumped',\n times: 10\n }\n };\n\n input.log(source);\n```\n\nwill be logged as:\n\n``` json\n { \"foo\": 1, \"bar\": 2, \"buzz\": {\"sheep\": \"jumped\", \"times\": 10 }}\n```\n\n### Searching\n[Searching][3] with node-loggly is easy. All you have to do is use the search() method defined on each Loggly client:\n\n``` js\n var util = require('util');\n \n client.search('404', function (err, results) {\n // Inspect the result set\n util.inspect(results.data);\n });\n```\n\nThe search() exposes a chainable interface that allows you to set additional search parameters such as: ip, input name, rows, start, end, etc. \n\n``` js\n var util = require('util');\n \n client.search('404')\n .meta({ ip: '127.0.0.1', inputname: test })\n .context({ rows: 10 })\n .run(function (err, results) {\n // Inspect the result set\n util.inspect(results.data);\n });\n```\n\nThe context of the search (set using the `.context()` method) represents additional parameters in the Loggly API besides the search query itself. See the [Search API documentation][9] for a list of all options.\n\nMetadata set using the `.meta()` method is data that is set in the query parameter of your Loggly search, but `:` delimited. For more information about search queries in Loggly, check out the [Search Language Guide][4] on the [Loggly Wiki][5].\n\n### Facet Searching\nLoggly also exposes searches that can return counts of events over a time range. These are called [facets][6]. The valid facets are 'ip', 'date', and 'input'. Performing a facet search is very similar to a normal search: \n\n``` js\n var util = require('util');\n \n client.facet('ip', '404')\n .context({ buckets: 10 })\n .run(function (err, results) {\n // Inspect the result set\n util.inspect(results.data);\n });\n```\n\nThe chaining and options for the facet method(s) are the same as the search method above. \n\n### Working with Devices and Inputs\nLoggly exposes several entities that are available through node-loggly: inputs and devices. For more information about these terms, checkout the [Loggly Jargon][7] on the wiki. There are several methods available in node-loggly to work with these entities: \n\n``` js\n //\n // Returns all inputs associated with your account\n //\n client.getInputs(function (err, inputs) { /* ... */ });\n \n //\n // Returns an input with the specified name\n //\n client.getInput('input-name', function (err, input) { /* ... */ });\n \n //\n // Returns all devices associated with your account\n //\n client.getDevices(function (err, devices) { /* ... */ });\n```\n\n## Run Tests\nAll of the node-loggly tests are written in [vows][8], and cover all of the use cases described above. You will need to add your Loggly username, password, subdomain, and a two test inputs to test/data/test-config.json before running tests. When configuring the test inputs on Loggly, the first test input should be named 'test' using the HTTP service. The second input should be name 'test_json' using the HTTP service with the JSON logging option enabled:\n\n``` js\n {\n \"subdomain\": \"your-subdomain\",\n \"auth\": {\n \"username\": \"your-username\",\n \"password\": \"your-password\"\n },\n \"inputs\": {\n \"test\": {\n //\n // Token and ID of your plain-text input.\n //\n \"token\": \"your-really-long-token-you-got-when-you-created-an-http-input\",\n \"id\": 000\n },\n \"test_json\": {\n //\n // Token and ID of your JSON input.\n //\n \"token\": \"your-really-long-token-you-got-when-you-created-an-http-input\",\n \"id\": 001\n },\n }\n }\n```\n\nOnce you have valid Loggly credentials you can run tests with [vows][8]:\n\n``` bash\n $ npm test\n```\n\n#### Author: [Charlie Robbins](http://www.github.com/indexzero)\n#### Contributors: [Marak Squires](http://github.com/marak), [hij1nx](http://github.com/hij1nx), [Kord Campbell](http://loggly.com), [Erik Hedenström](http://github.com/ehedenst),\n\n[0]: http://wiki.loggly.com/apidocumentation\n[1]: http://wiki.loggly.com/loggingfromcode\n[3]: http://wiki.loggly.com/retrieve_events#search_uri\n[4]: http://wiki.loggly.com/searchguide\n[5]: http://wiki.loggly.com/\n[6]: http://wiki.loggly.com/retrieve_events#facet_uris\n[7]: http://wiki.loggly.com/loggingjargon\n[8]: http://vowsjs.org\n[9]: http://wiki.loggly.com/retrieve_events#optional\n", + "readmeFilename": "README.md", "_id": "loggly@0.3.11", "_from": "loggly@0.3.x >=0.3.7" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/package.json index 03b2977..7d63e43 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/package.json @@ -22,6 +22,7 @@ "long-stack-traces": "0.1.2" }, "readme": "# stack-trace\n\nGet v8 stack traces as an array of CallSite objects.\n\n## Install\n\n``` bash\nnpm install stack-trace\n```\n\n## Usage\n\nThe stack-trace module makes it easy for you to capture the current stack:\n\n``` javascript\nvar stackTrace = require('stack-trace');\nvar trace = stackTrace.get();\n\nrequire('assert').strictEqual(trace[0].getFileName(), __filename);\n```\n\nHowever, sometimes you have already popped the stack you are interested in,\nand all you have left is an `Error` object. This module can help:\n\n``` javascript\nvar stackTrace = require('stack-trace');\nvar err = new Error('something went wrong');\nvar trace = stackTrace.parse(err);\n\nrequire('assert').strictEqual(trace[0].getFileName(), __filename);\n```\n\nPlease note that parsing the `Error#stack` property is not perfect, only\ncertain properties can be retrieved with it as noted in the API docs below.\n\n## Long stack traces\n\nstack-trace works great with [long-stack-traces][], when parsing an `err.stack`\nthat has crossed the event loop boundary, a `CallSite` object returning\n`'----------------------------------------'` for `getFileName()` is created.\nAll other methods of the event loop boundary call site return `null`.\n\n[long-stack-traces]: https://github.com/tlrobinson/long-stack-traces\n\n## API\n\n### stackTrace.get([belowFn])\n\nReturns an array of `CallSite` objects, where element `0` is the current call\nsite.\n\nWhen passing a function on the current stack as the `belowFn` parameter, the\nreturned array will only include `CallSite` objects below this function.\n\n### stackTrace.parse(err)\n\nParses the `err.stack` property of an `Error` object into an array compatible\nwith those returned by `stackTrace.get()`. However, only the following methods\nare implemented on the returned `CallSite` objects.\n\n* getTypeName\n* getFunctionName\n* getMethodName\n* getFileName\n* getLineNumber\n* getColumnNumber\n* isNative\n\nNote: Except `getFunctionName()`, all of the above methods return exactly the\nsame values as you would get from `stackTrace.get()`. `getFunctionName()`\nis sometimes a little different, but still useful.\n\n### CallSite\n\nThe official v8 CallSite object API can be found [here][v8stackapi]. A quick\nexcerpt:\n\n> A CallSite object defines the following methods:\n>\n> * **getThis**: returns the value of this\n> * **getTypeName**: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object's [[Class]] internal property.\n> * **getFunction**: returns the current function\n> * **getFunctionName**: returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function's context.\n> * **getMethodName**: returns the name of the property of this or one of its prototypes that holds the current function\n> * **getFileName**: if this function was defined in a script returns the name of the script\n> * **getLineNumber**: if this function was defined in a script returns the current line number\n> * **getColumnNumber**: if this function was defined in a script returns the current column number\n> * **getEvalOrigin**: if this function was created using a call to eval returns a CallSite object representing the location where eval was called\n> * **isToplevel**: is this a toplevel invocation, that is, is this the global object?\n> * **isEval**: does this call take place in code defined by a call to eval?\n> * **isNative**: is this call in native V8 code?\n> * **isConstructor**: is this a constructor call?\n\n[v8stackapi]: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi\n\n## License\n\nstack-trace is licensed under the MIT license.\n", + "readmeFilename": "Readme.md", "_id": "stack-trace@0.0.6", "_from": "stack-trace@0.0.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/package.json index 442baa2..5729bd2 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/package.json @@ -44,6 +44,7 @@ "node": ">= 0.4.0" }, "readme": "# winston [![Build Status](https://secure.travis-ci.org/flatiron/winston.png)](http://travis-ci.org/flatiron/winston)\n\nA multi-transport async logging library for node.js. "CHILL WINSTON! ... I put it in the logs."\n\n## Installation\n\n### Installing npm (node package manager)\n```\n curl http://npmjs.org/install.sh | sh\n```\n\n### Installing winston\n```\n [sudo] npm install winston\n```\n\n## Motivation\nWinston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each instance of a winston logger can have multiple transports configured at different levels. For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file. \n\nThere also seemed to be a lot of logging libraries out there that coupled their implementation of logging (i.e. how the logs are stored / indexed) to the API that they exposed to the programmer. This library aims to decouple those parts of the process to make it more flexible and extensible.\n\n## Usage\nThere are two different ways to use winston: directly via the default logger, or by instantiating your own Logger. The former is merely intended to be a convenient shared logger to use throughout your application if you so choose. \n\n### Using the Default Logger\nThe default logger is accessible through the winston module directly. Any method that you could call on an instance of a logger is available on the default logger:\n\n``` js\n var winston = require('winston');\n \n winston.log('info', 'Hello distributed log files!');\n winston.info('Hello again distributed logs');\n```\n\nBy default, only the Console transport is set on the default logger. You can add or remove transports via the add() and remove() methods:\n\n``` js\n winston.add(winston.transports.File, { filename: 'somefile.log' });\n winston.remove(winston.transports.Console);\n```\n\nFor more documenation about working with each individual transport supported by Winston see the \"Working with Transports\" section below. \n\n### Instantiating your own Logger\nIf you would prefer to manage the object lifetime of loggers you are free to instantiate them yourself:\n\n``` js\n var logger = new (winston.Logger)({\n transports: [\n new (winston.transports.Console)(),\n new (winston.transports.File)({ filename: 'somefile.log' })\n ]\n });\n```\n\nYou can work with this logger in the same way that you work with the default logger: \n\n``` js\n //\n // Logging\n //\n logger.log('info', 'Hello distributed log files!');\n logger.info('Hello again distributed logs');\n \n //\n // Adding / Removing Transports\n // (Yes It's chainable)\n //\n logger.add(winston.transports.File)\n .remove(winston.transports.Console);\n```\n\n### Handling Uncaught Exceptions with winston\n\nWith `winston`, it is possible to catch and log `uncaughtException` events from your process. There are two distinct ways of enabling this functionality either through the default winston logger or your own logger instance.\n\nIf you want to use this feature with the default logger simply call `.handleExceptions()` with a transport instance.\n\n``` js\n //\n // You can add a separate exception logger by passing it to `.handleExceptions`\n //\n winston.handleExceptions(new winston.transports.File({ filename: 'path/to/exceptions.log' }))\n \n //\n // Alternatively you can set `.handleExceptions` to true when adding transports to winston\n //\n winston.add(winston.transports.File, { \n filename: 'path/to/all-logs.log', \n handleExceptions: true \n });\n```\n\n## to exit or not to exit\n\nby default, winston will exit after logging an uncaughtException. if this is not the behavior you want,\nset `exitOnError = false`\n\n``` js\n var logger = new (winston.Logger)({ exitOnError: false });\n\n //\n // or, like this:\n //\n logger.exitOnError = false;\n```\n\nWhen working with custom logger instances, you can pass in separate transports to the `exceptionHandlers` property or set `.handleExceptions` on any transport.\n\n``` js\n var logger = new (winston.Logger)({\n transports: [\n new winston.transports.File({ filename: 'path/to/all-logs.log' })\n ]\n exceptionHandlers: [\n new winston.transports.File({ filename: 'path/to/exceptions.log' })\n ]\n });\n```\n\nThe `exitOnError` option can also be a function to prevent exit on only certain types of errors:\n\n``` js\n function ignoreEpipe(err) {\n return err.code !== 'EPIPE';\n }\n\n var logger = new (winston.Logger)({ exitOnError: ignoreEpipe });\n\n //\n // or, like this:\n //\n logger.exitOnError = ignoreEpipe;\n```\n\n### Using Logging Levels\nSetting the level for your logging message can be accomplished in one of two ways. You can pass a string representing the logging level to the log() method or use the level specified methods defined on every winston Logger. \n\n``` js\n //\n // Any logger instance\n //\n logger.log('info', \"127.0.0.1 - there's no place like home\");\n logger.info(\"127.0.0.1 - there's no place like home\");\n \n //\n // Default logger\n //\n winston.log('info', \"127.0.0.1 - there's no place like home\");\n winston.info(\"127.0.0.1 - there's no place like home\");\n```\n\nAs of 0.2.0, winston supports customizable logging levels, defaulting to [npm][0] style logging levels. Changing logging levels is easy:\n\n``` js\n //\n // Change levels on the default winston logger\n //\n winston.setLevels(winston.config.syslog.levels);\n \n //\n // Change levels on an instance of a logger\n //\n logger.setLevels(winston.config.syslog.levels);\n```\n\nCalling `.setLevels` on a logger will remove all of the previous helper methods for the old levels and define helper methods for the new levels. Thus, you should be careful about the logging statements you use when changing levels. For example, if you ran this code after changing to the syslog levels:\n\n``` js\n //\n // Logger does not have 'silly' defined since that level is not in the syslog levels \n //\n logger.silly('some silly message');\n```\n\n### Using Custom Logging Levels\nIn addition to the predefined `npm` and `syslog` levels available in Winston, you can also choose to define your own:\n\n``` js\n var myCustomLevels = {\n levels: {\n foo: 0,\n bar: 1,\n baz: 2,\n foobar: 3\n },\n colors: {\n foo: 'blue',\n bar: 'green',\n baz: 'yellow',\n foobar: 'red'\n }\n };\n \n var customLevelLogger = new (winston.Logger)({ levels: myCustomLevels.levels }); \n customLevelLogger.foobar('some foobar level-ed message');\n```\n\nAlthough there is slight repetition in this data structure, it enables simple encapsulation if you not to have colors. If you do wish to have colors, in addition to passing the levels to the Logger itself, you must make winston aware of them:\n\n``` js\n //\n // Make winston aware of these colors\n //\n winston.addColors(myCustomLevels.colors);\n```\n\nThis enables transports with the 'colorize' option set to appropriately color the output of custom levels.\n\n### Events and Callbacks in Winston\nEach instance of winston.Logger is also an instance of an [EventEmitter][1]. A log event will be raised each time a transport successfully logs a message:\n\n``` js\n logger.on('logging', function (transport, level, msg, meta) {\n // [msg] and [meta] have now been logged at [level] to [transport]\n });\n \n logger.info('CHILL WINSTON!', { seriously: true });\n```\n\nIt is also worth mentioning that the logger also emits an 'error' event which you should handle or suppress if you don't want unhandled exceptions:\n\n``` js\n //\n // Handle errors\n //\n logger.on('error', function (err) { /* Do Something */ });\n \n //\n // Or just suppress them.\n //\n logger.emitErrs = false;\n```\n\nEvery logging method described in the previous section also takes an optional callback which will be called only when all of the transports have logged the specified message.\n\n``` js\n logger.info('CHILL WINSTON!', { seriously: true }, function (err, level, msg, meta) {\n // [msg] and [meta] have now been logged at [level] to **every** transport.\n });\n```\n\n### Working with multiple Loggers in winston\n\nOften in larger, more complex applications it is necessary to have multiple logger instances with different settings. Each logger is responsible for a different feature area (or category). This is exposed in `winston` in two ways: through `winston.loggers` and instances of `winston.Container`. In fact, `winston.loggers` is just a predefined instance of `winston.Container`:\n\n``` js\n var winston = require('winston');\n \n //\n // Configure the logger for `category1`\n //\n winston.loggers.add('category1', {\n console: {\n level: 'silly',\n colorize: 'true'\n },\n file: {\n filename: '/path/to/some/file'\n }\n });\n \n //\n // Configure the logger for `category2`\n //\n winston.loggers.add('category2', {\n couchdb: {\n host: '127.0.0.1',\n port: 5984\n }\n });\n```\n\nNow that your loggers are setup you can require winston _in any file in your application_ and access these pre-configured loggers:\n\n``` js\n var winston = require('winston');\n \n //\n // Grab your preconfigured logger\n //\n var category1 = winston.loggers.get('category1');\n \n category1.info('logging from your IoC container-based logger');\n```\n\nIf you prefer to manage the `Container` yourself you can simply instantiate one:\n\n``` js\n var winston = require('winston'),\n container = new winston.Container();\n \n container.add('category1', {\n console: {\n level: 'silly',\n colorize: 'true'\n },\n file: {\n filename: '/path/to/some/file'\n }\n });\n```\n\n### Sharing transports between Loggers in winston\n\n``` js\n var winston = require('winston');\n\n //\n // Setup transports to be shared across all loggers\n // in three ways:\n //\n // 1. By setting it on the default Container\n // 2. By passing `transports` into the constructor function of winston.Container\n // 3. By passing `transports` into the `.get()` or `.add()` methods \n //\n\n //\n // 1. By setting it on the default Container\n //\n winston.loggers.options.transports = [\n // Setup your shared transports here\n ];\n\n //\n // 2. By passing `transports` into the constructor function of winston.Container\n //\n var container = new winston.Container({\n transports: [\n // Setup your shared transports here\n ]\n });\n\n //\n // 3. By passing `transports` into the `.get()` or `.add()` methods \n // \n winston.loggers.add('some-category', {\n transports: [\n // Setup your shared transports here\n ]\n });\n\n container.add('some-category', {\n transports: [\n // Setup your shared transports here\n ]\n });\n```\n\n### Logging with Metadata\nIn addition to logging string messages, winston will also optionally log additional JSON metadata objects. Adding metadata is simple:\n\n``` js\n winston.log('info', 'Test Log Message', { anything: 'This is metadata' });\n```\n\nThe way these objects is stored varies from transport to transport (to best support the storage mechanisms offered). Here's a quick summary of how each transports handles metadata:\n\n1. __Console:__ Logged via util.inspect(meta)\n2. __File:__ Logged via util.inspect(meta)\n3. __Loggly:__ Logged in suggested [Loggly format][2]\n\n### Profiling with Winston\nIn addition to logging messages and metadata, winston also has a simple profiling mechanism implemented for any logger:\n\n``` js\n //\n // Start profile of 'test'\n // Remark: Consider using Date.now() with async operations \n //\n winston.profile('test');\n \n setTimeout(function () {\n //\n // Stop profile of 'test'. Logging will now take place:\n // \"17 Jan 21:00:00 - info: test duration=1000ms\"\n //\n winston.profile('test');\n }, 1000);\n``` \n\nAll profile messages are set to the 'info' by default and both message and metadata are optional There are no plans in the Roadmap to make this configurable, but I'm open to suggestions / issues.\n\n### Using winston in a CLI tool\nA common use-case for logging is output to a CLI tool. Winston has a special helper method which will pretty print output from your CLI tool. Here's an example from the [require-analyzer][15] written by [Nodejitsu][5]:\n\n```\n info: require-analyzer starting in /Users/Charlie/Nodejitsu/require-analyzer\n info: Found existing dependencies\n data: {\n data: colors: '0.x.x',\n data: eyes: '0.1.x',\n data: findit: '0.0.x',\n data: npm: '1.0.x',\n data: optimist: '0.2.x',\n data: semver: '1.0.x',\n data: winston: '0.2.x'\n data: }\n info: Analyzing dependencies...\n info: Done analyzing raw dependencies\n info: Retrieved packages from npm\n warn: No additional dependencies found\n```\n\nConfiguring output for this style is easy, just use the `.cli()` method on `winston` or an instance of `winston.Logger`:\n\n``` js\n var winston = require('winston');\n \n //\n // Configure CLI output on the default logger\n //\n winston.cli();\n \n //\n // Configure CLI on an instance of winston.Logger\n //\n var logger = new winston.Logger({\n transports: [\n new (winston.transports.Console)()\n ]\n });\n \n logger.cli();\n```\n\n### Extending another object with Logging functionality\nOften in a given code base with lots of Loggers it is useful to add logging methods a different object so that these methods can be called with less syntax. Winston exposes this functionality via the 'extend' method:\n\n``` js\n var myObject = {};\n \n logger.extend(myObject);\n \n //\n // You can now call logger methods on 'myObject'\n //\n myObject.info('127.0.0.1 - there's no place like home');\n```\n\n## Working with Transports\nRight now there are four transports supported by winston core. If you have a transport you would like to add either open an issue or fork and submit a pull request. Commits are welcome, but I'll give you extra street cred if you __add tests too :D__\n \n1. __Console:__ Output to the terminal\n2. __Files:__ Append to a file\n3. __Loggly:__ Log to Logging-as-a-Service platform Loggly\n\n### Console Transport\n``` js\n winston.add(winston.transports.Console, options)\n```\n\nThe Console transport takes two simple options:\n\n* __level:__ Level of messages that this transport should log (default 'debug').\n* __silent:__ Boolean flag indicating whether to suppress output (default false).\n* __colorize:__ Boolean flag indicating if we should colorize output (default false).\n* __timestamp:__ Boolean flag indicating if we should prepend output with timestamps (default false). If function is specified, its return value will be used instead of timestamps.\n\n*Metadata:* Logged via util.inspect(meta);\n\n### File Transport\n``` js\n winston.add(winston.transports.File, options)\n```\n\nThe File transport should really be the 'Stream' transport since it will accept any [WritableStream][14]. It is named such because it will also accept filenames via the 'filename' option:\n\n* __level:__ Level of messages that this transport should log.\n* __silent:__ Boolean flag indicating whether to suppress output.\n* __colorize:__ Boolean flag indicating if we should colorize output.\n* __timestamp:__ Boolean flag indicating if we should prepend output with timestamps (default false). If function is specified, its return value will be used instead of timestamps.\n* __filename:__ The filename of the logfile to write output to.\n* __maxsize:__ Max size in bytes of the logfile, if the size is exceeded then a new file is created.\n* __maxFiles:__ Limit the number of files created when the size of the logfile is exceeded.\n* __stream:__ The WriteableStream to write output to.\n* __json:__ If true, messages will be logged as JSON (default true).\n\n*Metadata:* Logged via util.inspect(meta);\n\n### Loggly Transport\n``` js\n winston.add(winston.transports.Loggly, options);\n```\n\nThe Loggly transport is based on [Nodejitsu's][5] [node-loggly][6] implementation of the [Loggly][7] API. If you haven't heard of Loggly before, you should probably read their [value proposition][8]. The Loggly transport takes the following options. Either 'inputToken' or 'inputName' is required:\n\n* __level:__ Level of messages that this transport should log. \n* __subdomain:__ The subdomain of your Loggly account. *[required]*\n* __auth__: The authentication information for your Loggly account. *[required with inputName]*\n* __inputName:__ The name of the input this instance should log to.\n* __inputToken:__ The input token of the input this instance should log to.\n* __json:__ If true, messages will be sent to Loggly as JSON.\n\n*Metadata:* Logged in suggested [Loggly format][2]\n\n### Riak Transport\nAs of `0.3.0` the Riak transport has been broken out into a new module: [winston-riak][17]. Using it is just as easy:\n\n``` js\n var Riak = require('winston-riak').Riak;\n winston.add(Riak, options);\n```\n\nIn addition to the options accepted by the [riak-js][3] [client][4], the Riak transport also accepts the following options. It is worth noting that the riak-js debug option is set to *false* by default:\n\n* __level:__ Level of messages that this transport should log.\n* __bucket:__ The name of the Riak bucket you wish your logs to be in or a function to generate bucket names dynamically.\n\n``` js\n // Use a single bucket for all your logs\n var singleBucketTransport = new (Riak)({ bucket: 'some-logs-go-here' });\n \n // Generate a dynamic bucket based on the date and level\n var dynamicBucketTransport = new (Riak)({\n bucket: function (level, msg, meta, now) {\n var d = new Date(now);\n return level + [d.getDate(), d.getMonth(), d.getFullYear()].join('-');\n }\n });\n```\n\n*Metadata:* Logged as JSON literal in Riak\n\n### MongoDB Transport\nAs of `0.3.0` the MongoDB transport has been broken out into a new module: [winston-mongodb][16]. Using it is just as easy:\n\n``` js\n var MongoDB = require('winston-mongodb').MongoDB;\n winston.add(MongoDB, options);\n```\n\nThe MongoDB transport takes the following options. 'db' is required:\n\n* __level:__ Level of messages that this transport should log. \n* __silent:__ Boolean flag indicating whether to suppress output.\n* __db:__ The name of the database you want to log to. *[required]*\n* __collection__: The name of the collection you want to store log messages in, defaults to 'log'.\n* __safe:__ Boolean indicating if you want eventual consistency on your log messages, if set to true it requires an extra round trip to the server to ensure the write was committed, defaults to true.\n* __host:__ The host running MongoDB, defaults to localhost.\n* __port:__ The port on the host that MongoDB is running on, defaults to MongoDB's default port.\n\n*Metadata:* Logged as a native JSON object.\n\n### SimpleDB Transport\n\nThe [winston-simpledb][18] transport is just as easy:\n\n``` js\n var SimpleDB = require('winston-simpledb').SimpleDB;\n winston.add(SimpleDB, options);\n```\n\nThe SimpleDB transport takes the following options. All items marked with an asterisk are required:\n\n* __awsAccessKey__:* your AWS Access Key\n* __secretAccessKey__:* your AWS Secret Access Key\n* __awsAccountId__:* your AWS Account Id\n* __domainName__:* a string or function that returns the domain name to log to\n* __region__:* the region your domain resides in\n* __itemName__: a string ('uuid', 'epoch', 'timestamp') or function that returns the item name to log\n\n*Metadata:* Logged as a native JSON object to the 'meta' attribute of the item.\n\n### Mail Transport\n\nThe [winston-mail][19] is an email transport:\n\n``` js\n var Mail = require('winston-mail').Mail;\n winston.add(Mail, options);\n```\n\nThe Mail transport uses [node-mail][20] behind the scenes. Options are the following, `to` and `host` are required:\n\n* __to:__ The address(es) you want to send to. *[required]*\n* __from:__ The address you want to send from. (default: `winston@[server-host-name]`)\n* __host:__ SMTP server hostname\n* __port:__ SMTP port (default: 587 or 25)\n* __secure:__ Use secure\n* __username__ User for server auth\n* __password__ Password for server auth\n* __level:__ Level of messages that this transport should log. \n* __silent:__ Boolean flag indicating whether to suppress output.\n\n*Metadata:* Stringified as JSON in email.\n\n### Amazon SNS (Simple Notification System) Transport\n\nThe [winston-sns][21] transport uses amazon SNS to send emails, texts, or a bunch of other notifications.\n\n``` js\n require('winston-sns').SNS;\n winston.add(winston.transports.SNS, options);\n```\n\nOptions:\n\n* __aws_key:__ Your Amazon Web Services Key. *[required]*\n* __aws_secret:__ Your Amazon Web Services Secret. *[required]*\n* __subscriber:__ Subscriber number - found in your SNS AWS Console, after clicking on a topic. Same as AWS Account ID. *[required]*\n* __topic_arn:__ Also found in SNS AWS Console - listed under a topic as Topic ARN. *[required]*\n* __region:__ AWS Region to use. Can be one of: `us-east-1`,`us-west-1`,`eu-west-1`,`ap-southeast-1`,`ap-northeast-1`,`us-gov-west-1`,`sa-east-1`. (default: `us-east-1`)\n* __subject:__ Subject for notifications. (default: \"Winston Error Report\")\n* __message:__ Message of notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: \"Level '%l' Error:\\n%e\\n\\nMetadata:\\n%m\")\n* __level:__ lowest level this transport will log. (default: `info`)\n\n### Graylog2 Transport\n\n[winston-graylog2][22] is a Graylog2 transport:\n\n``` js\n var Graylog2 = require('winston-graylog2').Graylog2;\n winston.add(Graylog2, options);\n```\n\nThe Graylog2 transport connects to a Graylog2 server over UDP using the following options:\n\n* __level:__ Level of messages this transport should log. (default: info)\n* __silent:__ Boolean flag indicating whether to suppress output. (default: false)\n\n* __graylogHost:__ IP address or hostname of the graylog2 server. (default: localhost)\n* __graylogPort:__ Port to send messages to on the graylog2 server. (default: 12201)\n* __graylogHostname:__ The hostname associated with graylog2 messages. (default: require('os').hostname())\n* __graylogFacility:__ The graylog2 facility to send log messages.. (default: nodejs)\n\n*Metadata:* Stringified as JSON in the full message GELF field.\n\n### Adding Custom Transports\nAdding a custom transport (say for one of the datastore on the Roadmap) is actually pretty easy. All you need to do is accept a couple of options, set a name, implement a log() method, and add it to the set of transports exposed by winston.\n\n``` js\n var util = require('util'),\n winston = require('winston');\n \n var CustomLogger = winston.transports.CustomerLogger = function (options) {\n //\n // Name this logger\n //\n this.name = 'customLogger';\n \n //\n // Set the level from your options\n //\n this.level = options.level || 'info';\n \n //\n // Configure your storage backing as you see fit\n //\n };\n \n //\n // Inherit from `winston.Transport` so you can take advantage\n // of the base functionality and `.handleExceptions()`.\n //\n util.inherits(CustomLogger, winston.Transport);\n \n CustomLogger.prototype.log = function (level, msg, meta, callback) {\n //\n // Store this message and metadata, maybe use some custom logic\n // then callback indicating success.\n //\n callback(null, true); \n };\n```\n\n## What's Next?\nWinston is stable and under active development. It is supported by and used at [Nodejitsu][5]. \n\n### Inspirations\n1. [npm][0]\n2. [log.js][9]\n3. [socket.io][10]\n4. [node-rlog][11]\n5. [BigBrother][12]\n6. [Loggly][7]\n\n### Road Map\n1. Improve support for adding custom Transports not defined in Winston core.\n2. Create API for reading from logs across all transports. \n3. Add more transports: Redis\n\n## Run Tests\nAll of the winston tests are written in [vows][13], and cover all of the use cases described above. You will need to add valid credentials for the various transports included to test/fixtures/test-config.json before running tests:\n\n``` js\n {\n \"transports\": {\n \"loggly\": {\n \"subdomain\": \"your-subdomain\",\n \"inputToken\": \"really-long-token-you-got-from-loggly\",\n \"auth\": {\n \"username\": \"your-username\",\n \"password\": \"your-password\"\n }\n }\n }\n }\n```\n\nOnce you have valid configuration and credentials you can run tests with [vows][13]:\n\n```\n vows --spec --isolate\n```\n\n#### Author: [Charlie Robbins](http://twitter.com/indexzero)\n#### Contributors: [Matthew Bergman](http://github.com/fotoverite), [Marak Squires](http://github.com/marak)\n\n[0]: https://github.com/isaacs/npm/blob/master/lib/utils/log.js\n[1]: http://nodejs.org/docs/v0.3.5/api/events.html#events.EventEmitter\n[2]: http://wiki.loggly.com/loggingfromcode\n[3]: http://riakjs.org\n[4]: https://github.com/frank06/riak-js/blob/master/src/http_client.coffee#L10\n[5]: http://nodejitsu.com\n[6]: http://github.com/nodejitsu/node-loggly\n[7]: http://loggly.com\n[8]: http://www.loggly.com/product/\n[9]: https://github.com/visionmedia/log.js\n[10]: http://socket.io\n[11]: https://github.com/jbrisbin/node-rlog\n[12]: https://github.com/feisty/BigBrother\n[13]: http://vowsjs.org\n[14]: http://nodejs.org/docs/v0.3.5/api/streams.html#writable_Stream\n[15]: http://github.com/nodejitsu/require-analyzer\n[16]: http://github.com/indexzero/winston-mongodb\n[17]: http://github.com/indexzero/winston-riak\n[18]: http://github.com/appsattic/winston-simpledb\n[19]: http://github.com/wavded/winston-mail\n[20]: https://github.com/weaver/node-mail\n[21]: https://github.com/jesseditson/winston-sns\n[22]: https://github.com/flite/winston-graylog2\n", + "readmeFilename": "README.md", "_id": "winston@0.5.11", "_from": "winston@0.5.x" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/package.json index d0eac39..8992f92 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/package.json @@ -46,6 +46,7 @@ "node": ">= 0.4.0" }, "readme": "# prompt [![Build Status](https://secure.travis-ci.org/flatiron/prompt.png)](http://travis-ci.org/flatiron/prompt)\n\nA beautiful command-line prompt for node.js\n\n## Features\n\n* prompts the user for input\n* supports validation and defaults\n* hides passwords\n\n## Installation\n\n### Installing npm (node package manager)\n```\ncurl http://npmjs.org/install.sh | sh\n```\n\n### Installing prompt\n```\n[sudo] npm install prompt\n```\n\n## Usage\nUsing prompt is relatively straight forward. There are two core methods you should be aware of: `prompt.get()` and `prompt.addProperties()`. There methods take strings representing property names in addition to objects for complex property validation (and more). There are a number of [examples][0] that you should examine for detailed usage.\n\n### Getting Basic Prompt Information\nGetting started with `prompt` is easy. Lets take a look at `examples/simple-prompt.js`:\n\n``` js\nvar prompt = require('prompt');\n\n//\n// Start the prompt\n//\nprompt.start();\n\n//\n// Get two properties from the user: username and email\n//\nprompt.get(['username', 'email'], function (err, result) {\n //\n // Log the results.\n //\n console.log('Command-line input received:');\n console.log(' username: ' + result.username);\n console.log(' email: ' + result.email);\n})\n```\n\nThis will result in the following command-line output:\n\n```\n$ node examples/simple-prompt.js \nprompt: username: some-user\nprompt: email: some-user@some-place.org\nCommand-line input received:\n username: some-user\n email: some-user@some-place.org\n```\n\n### Prompting with Validation, Default Values, and More (Complex Properties)\nIn addition to prompting the user with simple string prompts, there is a robust API for getting and validating complex information from a command-line prompt. Here's a quick sample:\n\n``` js\nvar properties = [\n {\n name: 'name', \n validator: /^[a-zA-Z\\s\\-]+$/,\n warning: 'Name must be only letters, spaces, or dashes',\n empty: false\n },\n {\n name: 'password',\n hidden: true\n }\n];\n\n//\n// Start the prompt\n//\nprompt.start();\n\n//\n// Get two properties from the user: email, password\n//\nprompt.get(properties, function (err, result) {\n //\n // Log the results.\n //\n console.log('Command-line input received:');\n console.log(' name: ' + result.name);\n console.log(' password: ' + result.password);\n});\n```\n\nPretty easy right? The output from the above script is: \n\n```\n$ node examples/property-prompt.js\nprompt: name: nodejitsu000\nerror: Invalid input for name\nerror: Name must be only letters, spaces, or dashes\nprompt: name: Nodejitsu Inc\nprompt: password: \nCommand-line input received:\n name: Nodejitsu Inc\n password: some-password \n```\n\n## Valid Property Settings\n`prompt` uses a simple property system for performing a couple of basic validation operations against input received from the command-line. The motivations here were speed and simplicity of implementation to integration of pseudo-standards like JSON-Schema were not feasible. \n\nLets examine the anatomy of a prompt property:\n\n``` js\n{\n message: 'Enter your password', // Prompt displayed to the user. If not supplied name will be used.\n name: 'password' // Key in the JSON object returned from `.get()`.\n validator: /^\\w+$/ // Regular expression that input must be valid against.\n warning: 'Password must be letters' // Warning message to display if validation fails.\n hidden: true // If true, characters entered will not be output to console.\n default: 'lamepassword' // Default value to use if no value is entered.\n empty: false // If false, value entered must be non-empty.\n}\n```\n### skipping prompts\n\nSometimes power users may wish to skip promts and specify all data as command line options. \nif a value is set as a property of `prompt.override` prompt will use that instead of \nprompting the user.\n\n``` js\n//prompt-everride.js\n\nvar prompt = require('prompt'),\n optimist = require('optimist')\n\n//\n// set the overrides\n//\nprompt.override = optimist.argv\n\n//\n// Start the prompt\n//\nprompt.start();\n\n//\n// Get two properties from the user: username and email\n//\nprompt.get(['username', 'email'], function (err, result) {\n //\n // Log the results.\n //\n console.log('Command-line input received:');\n console.log(' username: ' + result.username);\n console.log(' email: ' + result.email);\n})\n\n//: node prompt-everride.js --username USER --email EMAIL\n\n```\n\n\n### Adding Properties to an Object \nA common use-case for prompting users for data from the command-line is to extend or create a configuration object that is passed onto the entry-point method for your CLI tool. `prompt` exposes a convenience method for doing just this: \n\n``` js\nvar obj = {\n password: 'lamepassword',\n mindset: 'NY'\n}\n\n//\n// Log the initial object.\n//\nconsole.log('Initial object to be extended:');\nconsole.dir(obj);\n\n//\n// Add two properties to the empty object: username and email\n//\nprompt.addProperties(obj, ['username', 'email'], function (err) {\n //\n // Log the results.\n //\n console.log('Updated object received:');\n console.dir(obj);\n});\n```\n\n## Customizing your prompt\nAside from changing `property.message`, you can also change `prompt.message`\nand `prompt.delimiter` to change the appearance of your prompt.\n\nThe basic structure of a prompt is this:\n\n``` js\nprompt.message + prompt.delimiter + property.message + prompt.delimiter;\n```\n\nThe default `prompt.message` is \"prompt,\" the default `prompt.delimiter` is\n\": \", and the default `property.message` is `property.name`.\nChanging these allows you to customize the appearance of your prompts! In\naddition, prompt supports ANSI color codes via the\n[colors module](https://github.com/Marak/colors.js) for custom colors. For a\nvery colorful example:\n\n``` js\nvar prompt = require(\"prompt\");\n//\n// The colors module adds color properties to String.prototype\n//\nrequire(\"colors\");\n\n//\n// Setting these properties customizes the prompt.\n//\nprompt.message = \"Question!\".rainbow;\nprompt.delimiter = \"><\".green;\n\nprompt.start();\n\nprompt.get([{ name: \"name\",\n message: \"What is your name?\".magenta }], function (err, result) {\n console.log(\"You said your name is: \".cyan + result.name.cyan);\n});\n```\n\n## Running tests\n```\nvows test/*-test.js --spec\n```\n\n#### Author: [Charlie Robbins][1]\n\n[0]: https://github.com/flatiron/prompt/tree/master/examples\n[1]: http://nodejitsu.com\n", + "readmeFilename": "README.md", "_id": "prompt@0.1.12", "_from": "prompt@~0.1.12" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/package.json index 6a2003b..f5daec9 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/package.json @@ -21,6 +21,7 @@ "semver": "./bin/semver" }, "readme": "semver(1) -- The semantic versioner for npm\n===========================================\n\n## Usage\n\n $ npm install semver\n\n semver.valid('1.2.3') // true\n semver.valid('a.b.c') // false\n semver.clean(' =v1.2.3 ') // '1.2.3'\n semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true\n semver.gt('1.2.3', '9.8.7') // false\n semver.lt('1.2.3', '9.8.7') // true\n\nAs a command-line utility:\n\n $ semver -h\n\n Usage: semver -v [-r ]\n Test if version(s) satisfy the supplied range(s),\n and sort them.\n\n Multiple versions or ranges may be supplied.\n\n Program exits successfully if any valid version satisfies\n all supplied ranges, and prints all satisfying versions.\n\n If no versions are valid, or ranges are not satisfied,\n then exits failure.\n\n Versions are printed in ascending order, so supplying\n multiple versions to the utility will just sort them.\n\n## Versions\n\nA version is the following things, in this order:\n\n* a number (Major)\n* a period\n* a number (minor)\n* a period\n* a number (patch)\n* OPTIONAL: a hyphen, followed by a number (build)\n* OPTIONAL: a collection of pretty much any non-whitespace characters\n (tag)\n\nA leading `\"=\"` or `\"v\"` character is stripped off and ignored.\n\n## Comparisons\n\nThe ordering of versions is done using the following algorithm, given\ntwo versions and asked to find the greater of the two:\n\n* If the majors are numerically different, then take the one\n with a bigger major number. `2.3.4 > 1.3.4`\n* If the minors are numerically different, then take the one\n with the bigger minor number. `2.3.4 > 2.2.4`\n* If the patches are numerically different, then take the one with the\n bigger patch number. `2.3.4 > 2.3.3`\n* If only one of them has a build number, then take the one with the\n build number. `2.3.4-0 > 2.3.4`\n* If they both have build numbers, and the build numbers are numerically\n different, then take the one with the bigger build number.\n `2.3.4-10 > 2.3.4-9`\n* If only one of them has a tag, then take the one without the tag.\n `2.3.4 > 2.3.4-beta`\n* If they both have tags, then take the one with the lexicographically\n larger tag. `2.3.4-beta > 2.3.4-alpha`\n* At this point, they're equal.\n\n## Ranges\n\nThe following range styles are supported:\n\n* `>1.2.3` Greater than a specific version.\n* `<1.2.3` Less than\n* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`\n* `~1.2.3` := `>=1.2.3 <1.3.0`\n* `~1.2` := `>=1.2.0 <2.0.0`\n* `~1` := `>=1.0.0 <2.0.0`\n* `1.2.x` := `>=1.2.0 <1.3.0`\n* `1.x` := `>=1.0.0 <2.0.0`\n\nRanges can be joined with either a space (which implies \"and\") or a\n`||` (which implies \"or\").\n\n## Functions\n\n* valid(v): Return the parsed version, or null if it's not valid.\n* inc(v, release): Return the version incremented by the release type\n (major, minor, patch, or build), or null if it's not valid.\n\n### Comparison\n\n* gt(v1, v2): `v1 > v2`\n* gte(v1, v2): `v1 >= v2`\n* lt(v1, v2): `v1 < v2`\n* lte(v1, v2): `v1 <= v2`\n* eq(v1, v2): `v1 == v2` This is true if they're logically equivalent,\n even if they're not the exact same string. You already know how to\n compare strings.\n* neq(v1, v2): `v1 != v2` The opposite of eq.\n* cmp(v1, comparator, v2): Pass in a comparison string, and it'll call\n the corresponding function above. `\"===\"` and `\"!==\"` do simple\n string comparison, but are included for completeness. Throws if an\n invalid comparison string is provided.\n* compare(v1, v2): Return 0 if v1 == v2, or 1 if v1 is greater, or -1 if\n v2 is greater. Sorts in ascending order if passed to Array.sort().\n* rcompare(v1, v2): The reverse of compare. Sorts an array of versions\n in descending order when passed to Array.sort().\n\n\n### Ranges\n\n* validRange(range): Return the valid range or null if it's not valid\n* satisfies(version, range): Return true if the version satisfies the\n range.\n* maxSatisfying(versions, range): Return the highest version in the list\n that satisfies the range, or null if none of them do.\n", + "readmeFilename": "README.md", "_id": "semver@1.0.14", "_from": "semver@~1.0.13" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/History.md new file mode 100644 index 0000000..2ad4405 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/History.md @@ -0,0 +1,5 @@ + +0.0.5 / 2012-11-12 +================== + + * Solved process.env issue in detector on certain version so linux. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/detector.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/detector.js index 045cd81..c09b46d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/detector.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/detector.js @@ -19,14 +19,26 @@ */ var detector = module.exports; +var normalize = function(path) { + var last = Array.prototype.pop.apply(path); + + if (process.platform !== "win32" && last !== '/') { + path += '/'; + } + + return path; +} + /** * Returns tmp dir. Thank you npm. * * @returns {String} tmp dir. */ detector.tmp = function() { - return process.env.TMPDIR + var temp = process.env.TMPDIR || process.env.TMP || process.env.TEMP || (process.platform === "win32" ? "c:\\windows\\temp\\" : "/tmp/") + + return normalize(temp); }; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/package.json index 48d5e4e..3df7344 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/package.json @@ -26,6 +26,7 @@ "node": ">= 0.6.0" }, "readme": "[![Build Status](https://secure.travis-ci.org/vesln/package.png)](http://travis-ci.org/vesln/package)\n\n# package - Easy package.json exports.\n\n## Intro\n\nThis module provides an easy and simple way to export package.json data.\n\n## Installation\n\n\t$ npm install package\n\n## Usage\n\n\tvar package = require('package')(module); // contains package.json data.\n\tvar yourAwesomeModule = {};\n\tyourAwesomeModule.version = package.version;\n\n## Tests\n\n\t$ make test\n\n## Contribution\n\nBug fixes and features are welcomed.\n\n## Other similar modules\n\n- pkginfo (https://github.com/indexzero/node-pkginfo) by indexzero.\n- JSON.parse + fs.readFile\n\n## License\n\nMIT License\n\nCopyright (C) 2012 Veselin Todorov\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\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject 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,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.", + "readmeFilename": "Readme.md", "_id": "package@1.0.1", "_from": "package@>= 1.0.0 < 1.2.0" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/package.json index de90244..ccf3ac5 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/package.json @@ -1,6 +1,6 @@ { "name": "temporary", - "version": "0.0.4", + "version": "0.0.5", "description": "The lord of tmp.", "keywords": [ "tmp", @@ -33,6 +33,7 @@ "node": ">= 0.6.0" }, "readme": "[![Build Status](https://secure.travis-ci.org/vesln/temporary.png)](http://travis-ci.org/vesln/temporary)\n\n# temporary - The lord of tmp.\n\n## Intro\n\nTemporary provides an easy way to create temporary files and directories.\nIt will create a temporary file/directory with a unique name.\n\n## Features\n\n- Generates unique name.\n- Auto-discovers tmp dir.\n\n## Installation\n\n\t$ npm install temporary\n\n## Usage\n\n\tvar Tempfile = require('temporary/file');\n\tvar Tempdir = require('temporary/dir');\n\tvar file = new Tempfile;\n\tvar dir = new Tempdir;\n\t\n\tconsole.log(file.path); // path.\n\tconsole.log(dir.path); // path.\n\t\n\tfile.unlink();\n\tdir.rmdir();\n\n## Methods\n\n### File\n\n- File.readFile\n- File.readFileSync\n- File.writeFile\n- File.writeFileSync\n- File.open\n- File.openSync\n- File.close\n- File.closeSync\n- File.unlink\n- File.unlinkSync\n\n### Dir\n\n- Dir.rmdir\n- Dir.rmdirSync\n\n## Tests\n\n\t$ make test\n\n## Contribution\n\nBug fixes and features are welcomed.\n\n## License\n\nMIT License\n\nCopyright (C) 2012 Veselin Todorov\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\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject 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,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.", - "_id": "temporary@0.0.4", + "readmeFilename": "Readme.md", + "_id": "temporary@0.0.5", "_from": "temporary@~0.0.4" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.html index 5f37ac0..abefdf1 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.html +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.html @@ -7,7 +7,7 @@ UglifyJS – a JavaScript parser/compressor/beautifier - + @@ -99,27 +99,28 @@

UglifyJS – a JavaScript parser/compressor/beautifier

Table of Contents
-

1 UglifyJS — a JavaScript parser/compressor/beautifier

+

1 NEW: UglifyJS2

+

+I started working on UglifyJS's successor, version 2. It's almost a full +rewrite (except for the parser which is heavily modified, everything else +starts from scratch). I've detailed my reasons in the README, see the +project page. +

+

+https://github.com/mishoo/UglifyJS2 +

+

+Version 1 will continue to be maintained for fixing show-stopper bugs, but +no new features should be expected. +

+

+Please help me focus on version 2 by making a donation! +

+
+ +
+ +
+

2 UglifyJS — a JavaScript parser/compressor/beautifier

+
+ +

This package implements a general-purpose JavaScript parser/compressor/beautifier toolkit. It is developed on NodeJS, but it @@ -233,9 +259,9 @@

1 UglifyJS — a JavaSc

-
-

1.1 Unsafe transformations

-
+
+

2.1 Unsafe transformations

+

@@ -246,9 +272,9 @@

1.1

-
-

1.1.1 Calls involving the global Array constructor

-
+
+

2.1.1 Calls involving the global Array constructor

+

@@ -316,9 +342,9 @@

1.1.1 Calls involving t

-
-

1.1.2 obj.toString() ==> obj+“”

-
+
+

2.1.2 obj.toString() ==> obj+“”

+
@@ -326,9 +352,9 @@

1.1.2 obj.toStrin

-
-

1.2 Install (NPM)

-
+
+

2.2 Install (NPM)

+

@@ -339,9 +365,9 @@

1.2 Install (NPM)

-
-

1.3 Install latest code from GitHub

-
+
+

2.3 Install latest code from GitHub

+
@@ -369,9 +395,9 @@

1.3 Install latest code f

-
-

1.4 Usage

-
+
+

2.4 Usage

+

@@ -407,6 +433,11 @@

1.4 Usage

+ +
  • -c or ----consolidate-primitive-values — consolidates null, Boolean, + and String values. Known as aliasing in the Closure Compiler. Worsens the + data compression ratio of gzip. +
  • --ascii — pass this argument to encode non-ASCII characters as \uXXXX sequences. By default UglifyJS won't bother to do it and will @@ -556,9 +587,9 @@

    1.4 Usage

  • -
    -

    1.4.1 API

    -
    +
    +

    2.4.1 API

    +

    @@ -727,9 +758,9 @@

    1.4.1 API

    -
    -

    1.4.2 Beautifier shortcoming – no more comments

    -
    +
    +

    2.4.2 Beautifier shortcoming – no more comments

    +

    @@ -749,9 +780,9 @@

    1.4.2 Beautifier shortc

    -
    -

    1.4.3 Use as a code pre-processor

    -
    +
    +

    2.4.3 Use as a code pre-processor

    +

    @@ -830,9 +861,9 @@

    1.4.3 Use as a code pre

    -
    -

    1.5 Compression – how good is it?

    -
    +
    +

    2.5 Compression – how good is it?

    +

    @@ -864,9 +895,9 @@

    1.5 Compression – h

    -
    -

    1.6 Bugs?

    -
    +
    +

    2.6 Bugs?

    +

    @@ -890,9 +921,9 @@

    1.6 Bugs?

    -
    -

    1.7 Links

    -
    +
    +

    2.7 Links

    +
      @@ -915,9 +946,9 @@

      1.7 Links

    -
    -

    1.8 License

    -
    +
    +

    2.8 License

    +

    @@ -971,7 +1002,7 @@

    Footnotes:

    -

    Date: 2011-12-09 14:59:08 EET

    +

    Date: 2012-08-27 12:38:12 EEST

    Author: Mihai Bazon

    Org version 7.7 with Emacs version 23

    Validate XHTML 1.0 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.org b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.org index d36b6b2..2588088 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.org +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.org @@ -5,6 +5,20 @@ #+AUTHOR: Mihai Bazon #+EMAIL: mihai.bazon@gmail.com +* NEW: UglifyJS2 + +I started working on UglifyJS's successor, version 2. It's almost a full +rewrite (except for the parser which is heavily modified, everything else +starts from scratch). I've detailed my reasons in the README, see the +project page. + +[[https://github.com/mishoo/UglifyJS2][https://github.com/mishoo/UglifyJS2]] + +Version 1 will continue to be maintained for fixing show-stopper bugs, but +no new features should be expected. + +Please help me focus on version 2 by [[http://pledgie.com/campaigns/18110][making a donation]]! + * UglifyJS --- a JavaScript parser/compressor/beautifier This package implements a general-purpose JavaScript @@ -390,7 +404,8 @@ function f(a, b, c) { - =except= -- an array of names to exclude from compression. - =defines= -- an object with properties named after symbols to replace (see the =--define= option for the script) and the values - representing the AST replacement value. + representing the AST replacement value. For example, + ={ defines: { DEBUG: ['name', 'false'], VERSION: ['string', '1.0'] } }= - =pro.ast_squeeze(ast, options)= -- employs further optimizations designed to reduce the size of the code that =gen_code= would generate from the diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/bin/uglifyjs b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/bin/uglifyjs index 455d2d8..34ed80e 100755 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/bin/uglifyjs +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/bin/uglifyjs @@ -9,327 +9,326 @@ var uglify = require("../uglify-js"), // symlink ~/.node_libraries/uglify-js.js pro = uglify.uglify; var options = { - ast: false, - consolidate: false, - mangle: true, - mangle_toplevel: false, - no_mangle_functions: false, - squeeze: true, - make_seqs: true, - dead_code: true, - verbose: false, - show_copyright: true, - out_same_file: false, - max_line_length: 32 * 1024, - unsafe: false, - reserved_names: null, - defines: { }, - lift_vars: false, - codegen_options: { - ascii_only: false, - beautify: false, - indent_level: 4, - indent_start: 0, - quote_keys: false, - space_colon: false, - inline_script: false - }, - make: false, - output: true // stdout + ast: false, + consolidate: false, + mangle: true, + mangle_toplevel: false, + no_mangle_functions: false, + squeeze: true, + make_seqs: true, + dead_code: true, + verbose: false, + show_copyright: true, + out_same_file: false, + max_line_length: 32 * 1024, + unsafe: false, + reserved_names: null, + defines: { }, + lift_vars: false, + codegen_options: { + ascii_only: false, + beautify: false, + indent_level: 4, + indent_start: 0, + quote_keys: false, + space_colon: false, + inline_script: false + }, + make: false, + output: true // stdout }; var args = jsp.slice(process.argv, 2); var filename; out: while (args.length > 0) { - var v = args.shift(); - switch (v) { - case "-b": - case "--beautify": - options.codegen_options.beautify = true; - break; - case "-c": - case "--consolidate-primitive-values": - options.consolidate = true; - break; - case "-i": - case "--indent": - options.codegen_options.indent_level = args.shift(); - break; - case "-q": - case "--quote-keys": - options.codegen_options.quote_keys = true; - break; - case "-mt": - case "--mangle-toplevel": - options.mangle_toplevel = true; - break; - case "-nmf": - case "--no-mangle-functions": - options.no_mangle_functions = true; - break; - case "--no-mangle": - case "-nm": - options.mangle = false; - break; - case "--no-squeeze": - case "-ns": - options.squeeze = false; - break; - case "--no-seqs": - options.make_seqs = false; - break; - case "--no-dead-code": - options.dead_code = false; - break; - case "--no-copyright": - case "-nc": - options.show_copyright = false; - break; - case "-o": - case "--output": - options.output = args.shift(); - break; - case "--overwrite": - options.out_same_file = true; - break; - case "-v": - case "--verbose": - options.verbose = true; - break; - case "--ast": - options.ast = true; - break; - case "--unsafe": - options.unsafe = true; - break; - case "--max-line-len": - options.max_line_length = parseInt(args.shift(), 10); - break; - case "--reserved-names": - options.reserved_names = args.shift().split(","); - break; - case "--lift-vars": - options.lift_vars = true; - break; - case "-d": - case "--define": - var defarg = args.shift(); - try { - var defsym = function(sym) { - // KEYWORDS_ATOM doesn't include NaN or Infinity - should we check - // for them too ?? We don't check reserved words and the like as the - // define values are only substituted AFTER parsing - if (jsp.KEYWORDS_ATOM.hasOwnProperty(sym)) { - throw "Don't define values for inbuilt constant '"+sym+"'"; - } - return sym; - }, - defval = function(v) { - if (v.match(/^"(.*)"$/) || v.match(/^'(.*)'$/)) { - return [ "string", RegExp.$1 ]; - } - else if (!isNaN(parseFloat(v))) { - return [ "num", parseFloat(v) ]; - } - else if (v.match(/^[a-z\$_][a-z\$_0-9]*$/i)) { - return [ "name", v ]; - } - else if (!v.match(/"/)) { - return [ "string", v ]; - } - else if (!v.match(/'/)) { - return [ "string", v ]; - } - throw "Can't understand the specified value: "+v; - }; - if (defarg.match(/^([a-z_\$][a-z_\$0-9]*)(=(.*))?$/i)) { - var sym = defsym(RegExp.$1), - val = RegExp.$2 ? defval(RegExp.$2.substr(1)) : [ 'name', 'true' ]; - options.defines[sym] = val; - } - else { - throw "The --define option expects SYMBOL[=value]"; - } - } catch(ex) { - sys.print("ERROR: In option --define "+defarg+"\n"+ex+"\n"); - process.exit(1); - } - break; - case "--define-from-module": - var defmodarg = args.shift(), - defmodule = require(defmodarg), - sym, - val; - for (sym in defmodule) { - if (defmodule.hasOwnProperty(sym)) { - options.defines[sym] = function(val) { - if (typeof val == "string") - return [ "string", val ]; - if (typeof val == "number") - return [ "num", val ]; - if (val === true) - return [ 'name', 'true' ]; - if (val === false) - return [ 'name', 'false' ]; - if (val === null) - return [ 'name', 'null' ]; - if (val === undefined) - return [ 'name', 'undefined' ]; - sys.print("ERROR: In option --define-from-module "+defmodarg+"\n"); - sys.print("ERROR: Unknown object type for: "+sym+"="+val+"\n"); - process.exit(1); - return null; - }(defmodule[sym]); - } + var v = args.shift(); + switch (v) { + case "-b": + case "--beautify": + options.codegen_options.beautify = true; + break; + case "-c": + case "--consolidate-primitive-values": + options.consolidate = true; + break; + case "-i": + case "--indent": + options.codegen_options.indent_level = args.shift(); + break; + case "-q": + case "--quote-keys": + options.codegen_options.quote_keys = true; + break; + case "-mt": + case "--mangle-toplevel": + options.mangle_toplevel = true; + break; + case "-nmf": + case "--no-mangle-functions": + options.no_mangle_functions = true; + break; + case "--no-mangle": + case "-nm": + options.mangle = false; + break; + case "--no-squeeze": + case "-ns": + options.squeeze = false; + break; + case "--no-seqs": + options.make_seqs = false; + break; + case "--no-dead-code": + options.dead_code = false; + break; + case "--no-copyright": + case "-nc": + options.show_copyright = false; + break; + case "-o": + case "--output": + options.output = args.shift(); + break; + case "--overwrite": + options.out_same_file = true; + break; + case "-v": + case "--verbose": + options.verbose = true; + break; + case "--ast": + options.ast = true; + break; + case "--unsafe": + options.unsafe = true; + break; + case "--max-line-len": + options.max_line_length = parseInt(args.shift(), 10); + break; + case "--reserved-names": + options.reserved_names = args.shift().split(","); + break; + case "--lift-vars": + options.lift_vars = true; + break; + case "-d": + case "--define": + var defarg = args.shift(); + try { + var defsym = function(sym) { + // KEYWORDS_ATOM doesn't include NaN or Infinity - should we check + // for them too ?? We don't check reserved words and the like as the + // define values are only substituted AFTER parsing + if (jsp.KEYWORDS_ATOM.hasOwnProperty(sym)) { + throw "Don't define values for inbuilt constant '"+sym+"'"; + } + return sym; + }, + defval = function(v) { + if (v.match(/^"(.*)"$/) || v.match(/^'(.*)'$/)) { + return [ "string", RegExp.$1 ]; + } + else if (!isNaN(parseFloat(v))) { + return [ "num", parseFloat(v) ]; + } + else if (v.match(/^[a-z\$_][a-z\$_0-9]*$/i)) { + return [ "name", v ]; } - break; - case "--ascii": - options.codegen_options.ascii_only = true; - break; - case "--make": - options.make = true; - break; - case "--inline-script": - options.codegen_options.inline_script = true; - break; - default: - filename = v; - break out; + else if (!v.match(/"/)) { + return [ "string", v ]; + } + else if (!v.match(/'/)) { + return [ "string", v ]; + } + throw "Can't understand the specified value: "+v; + }; + if (defarg.match(/^([a-z_\$][a-z_\$0-9]*)(=(.*))?$/i)) { + var sym = defsym(RegExp.$1), + val = RegExp.$2 ? defval(RegExp.$2.substr(1)) : [ 'name', 'true' ]; + options.defines[sym] = val; + } + else { + throw "The --define option expects SYMBOL[=value]"; + } + } catch(ex) { + sys.print("ERROR: In option --define "+defarg+"\n"+ex+"\n"); + process.exit(1); + } + break; + case "--define-from-module": + var defmodarg = args.shift(); + var defmodule = require(defmodarg); + var sym, val; + for (sym in defmodule) { + if (defmodule.hasOwnProperty(sym)) { + options.defines[sym] = function(val) { + if (typeof val == "string") + return [ "string", val ]; + if (typeof val == "number") + return [ "num", val ]; + if (val === true) + return [ 'name', 'true' ]; + if (val === false) + return [ 'name', 'false' ]; + if (val === null) + return [ 'name', 'null' ]; + if (val === undefined) + return [ 'name', 'undefined' ]; + sys.print("ERROR: In option --define-from-module "+defmodarg+"\n"); + sys.print("ERROR: Unknown object type for: "+sym+"="+val+"\n"); + process.exit(1); + return null; + }(defmodule[sym]); + } } + break; + case "--ascii": + options.codegen_options.ascii_only = true; + break; + case "--make": + options.make = true; + break; + case "--inline-script": + options.codegen_options.inline_script = true; + break; + default: + filename = v; + break out; + } } if (options.verbose) { - pro.set_logger(function(msg){ - sys.debug(msg); - }); + pro.set_logger(function(msg){ + sys.debug(msg); + }); } jsp.set_logger(function(msg){ - sys.debug(msg); + sys.debug(msg); }); if (options.make) { - options.out_same_file = false; // doesn't make sense in this case - var makefile = global.eval("(" + fs.readFileSync(filename || "Makefile.uglify.js").toString() + ")"); - var dir = path.dirname(filename); - output(makefile.files.map(function(file){ - var code = fs.readFileSync(path.join(dir, file.name)).toString(); - if (file.module) { - code = "!function(exports, global){global = this;\n" + code + "\n;this." + file.module + " = exports;}({})"; - } - else if (file.hide) { - code = "(function(){" + code + "}());"; - } - return squeeze_it(code); - }).join("\n")); + options.out_same_file = false; // doesn't make sense in this case + var makefile = global.eval("(" + fs.readFileSync(filename || "Makefile.uglify.js").toString() + ")"); + var dir = path.dirname(filename); + output(makefile.files.map(function(file){ + var code = fs.readFileSync(path.join(dir, file.name)).toString(); + if (file.module) { + code = "!function(exports, global){global = this;\n" + code + "\n;this." + file.module + " = exports;}({})"; + } + else if (file.hide) { + code = "(function(){" + code + "}());"; + } + return squeeze_it(code); + }).join("\n")); } else if (filename) { - fs.readFile(filename, "utf8", function(err, text){ - if (err) throw err; - output(squeeze_it(text)); - }); + fs.readFile(filename, "utf8", function(err, text){ + if (err) throw err; + output(squeeze_it(text)); + }); } else { - var stdin = process.openStdin(); - stdin.setEncoding("utf8"); - var text = ""; - stdin.on("data", function(chunk){ - text += chunk; - }); - stdin.on("end", function() { - output(squeeze_it(text)); - }); + var stdin = process.openStdin(); + stdin.setEncoding("utf8"); + var text = ""; + stdin.on("data", function(chunk){ + text += chunk; + }); + stdin.on("end", function() { + output(squeeze_it(text)); + }); } function output(text) { - var out; - if (options.out_same_file && filename) - options.output = filename; - if (options.output === true) { - out = process.stdout; - } else { - out = fs.createWriteStream(options.output, { - flags: "w", - encoding: "utf8", - mode: 0644 - }); - } - out.write(text.replace(/;*$/, ";")); - if (options.output !== true) { - out.end(); - } + var out; + if (options.out_same_file && filename) + options.output = filename; + if (options.output === true) { + out = process.stdout; + } else { + out = fs.createWriteStream(options.output, { + flags: "w", + encoding: "utf8", + mode: 0644 + }); + } + out.write(text.replace(/;*$/, ";")); + if (options.output !== true) { + out.end(); + } }; // --------- main ends here. function show_copyright(comments) { - var ret = ""; - for (var i = 0; i < comments.length; ++i) { - var c = comments[i]; - if (c.type == "comment1") { - ret += "//" + c.value + "\n"; - } else { - ret += "/*" + c.value + "*/"; - } + var ret = ""; + for (var i = 0; i < comments.length; ++i) { + var c = comments[i]; + if (c.type == "comment1") { + ret += "//" + c.value + "\n"; + } else { + ret += "/*" + c.value + "*/"; } - return ret; + } + return ret; }; function squeeze_it(code) { - var result = ""; - if (options.show_copyright) { - var tok = jsp.tokenizer(code), c; - c = tok(); - result += show_copyright(c.comments_before); + var result = ""; + if (options.show_copyright) { + var tok = jsp.tokenizer(code), c; + c = tok(); + result += show_copyright(c.comments_before); + } + try { + var ast = time_it("parse", function(){ return jsp.parse(code); }); + if (options.consolidate) ast = time_it("consolidate", function(){ + return consolidator.ast_consolidate(ast); + }); + if (options.lift_vars) { + ast = time_it("lift", function(){ return pro.ast_lift_variables(ast); }); } - try { - var ast = time_it("parse", function(){ return jsp.parse(code); }); - if (options.consolidate) ast = time_it("consolidate", function(){ - return consolidator.ast_consolidate(ast); - }); - if (options.lift_vars) { - ast = time_it("lift", function(){ return pro.ast_lift_variables(ast); }); - } - ast = time_it("mangle", function(){ - return pro.ast_mangle(ast, { - mangle : options.mangle, - toplevel : options.mangle_toplevel, - defines : options.defines, - except : options.reserved_names, - no_functions : options.no_mangle_functions - }); - }); - if (options.squeeze) ast = time_it("squeeze", function(){ - ast = pro.ast_squeeze(ast, { - make_seqs : options.make_seqs, - dead_code : options.dead_code, - keep_comps : !options.unsafe, - unsafe : options.unsafe - }); - if (options.unsafe) - ast = pro.ast_squeeze_more(ast); - return ast; - }); - if (options.ast) - return sys.inspect(ast, null, null); - result += time_it("generate", function(){ return pro.gen_code(ast, options.codegen_options) }); - if (!options.codegen_options.beautify && options.max_line_length) { - result = time_it("split", function(){ return pro.split_lines(result, options.max_line_length) }); - } - return result; - } catch(ex) { - sys.debug(ex.stack); - sys.debug(sys.inspect(ex)); - sys.debug(JSON.stringify(ex)); - process.exit(1); + ast = time_it("mangle", function(){ + return pro.ast_mangle(ast, { + mangle : options.mangle, + toplevel : options.mangle_toplevel, + defines : options.defines, + except : options.reserved_names, + no_functions : options.no_mangle_functions + }); + }); + if (options.squeeze) ast = time_it("squeeze", function(){ + ast = pro.ast_squeeze(ast, { + make_seqs : options.make_seqs, + dead_code : options.dead_code, + keep_comps : !options.unsafe, + unsafe : options.unsafe + }); + if (options.unsafe) + ast = pro.ast_squeeze_more(ast); + return ast; + }); + if (options.ast) + return sys.inspect(ast, null, null); + result += time_it("generate", function(){ return pro.gen_code(ast, options.codegen_options) }); + if (!options.codegen_options.beautify && options.max_line_length) { + result = time_it("split", function(){ return pro.split_lines(result, options.max_line_length) }); } + return result; + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + process.exit(1); + } }; function time_it(name, cont) { - if (!options.verbose) - return cont(); - var t1 = new Date().getTime(); - try { return cont(); } - finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } + if (!options.verbose) + return cont(); + var t1 = new Date().getTime(); + try { return cont(); } + finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } }; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/parse-js.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/parse-js.js index 0359d94..3728018 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/parse-js.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/parse-js.js @@ -60,80 +60,80 @@ /* -----[ Tokenizer (constants) ]----- */ var KEYWORDS = array_to_hash([ - "break", - "case", - "catch", - "const", - "continue", - "debugger", - "default", - "delete", - "do", - "else", - "finally", - "for", - "function", - "if", - "in", - "instanceof", - "new", - "return", - "switch", - "throw", - "try", - "typeof", - "var", - "void", - "while", - "with" + "break", + "case", + "catch", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "finally", + "for", + "function", + "if", + "in", + "instanceof", + "new", + "return", + "switch", + "throw", + "try", + "typeof", + "var", + "void", + "while", + "with" ]); var RESERVED_WORDS = array_to_hash([ - "abstract", - "boolean", - "byte", - "char", - "class", - "double", - "enum", - "export", - "extends", - "final", - "float", - "goto", - "implements", - "import", - "int", - "interface", - "long", - "native", - "package", - "private", - "protected", - "public", - "short", - "static", - "super", - "synchronized", - "throws", - "transient", - "volatile" + "abstract", + "boolean", + "byte", + "char", + "class", + "double", + "enum", + "export", + "extends", + "final", + "float", + "goto", + "implements", + "import", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "super", + "synchronized", + "throws", + "transient", + "volatile" ]); var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ - "return", - "new", - "delete", - "throw", - "else", - "case" + "return", + "new", + "delete", + "throw", + "else", + "case" ]); var KEYWORDS_ATOM = array_to_hash([ - "false", - "null", - "true", - "undefined" + "false", + "null", + "true", + "undefined" ]); var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); @@ -143,53 +143,53 @@ var RE_OCT_NUMBER = /^0[0-7]+$/; var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; var OPERATORS = array_to_hash([ - "in", - "instanceof", - "typeof", - "new", - "void", - "delete", - "++", - "--", - "+", - "-", - "!", - "~", - "&", - "|", - "^", - "*", - "/", - "%", - ">>", - "<<", - ">>>", - "<", - ">", - "<=", - ">=", - "==", - "===", - "!=", - "!==", - "?", - "=", - "+=", - "-=", - "/=", - "*=", - "%=", - ">>=", - "<<=", - ">>>=", - "|=", - "^=", - "&=", - "&&", - "||" + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" ]); -var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); +var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF")); var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:")); @@ -200,478 +200,479 @@ var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); /* -----[ Tokenizer ]----- */ var UNICODE = { // Unicode 6.1 - letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), - combining_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08E4-\\u08FE\\u0900-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C82\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D02\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1DC0-\\u1DE6\\u1DFC-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA674-\\uA67D\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), - connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"), - digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]") + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + combining_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08E4-\\u08FE\\u0900-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C82\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D02\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1DC0-\\u1DE6\\u1DFC-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA674-\\uA67D\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"), + digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]") }; function is_letter(ch) { - return UNICODE.letter.test(ch); + return UNICODE.letter.test(ch); }; function is_digit(ch) { - ch = ch.charCodeAt(0); - return ch >= 48 && ch <= 57; + ch = ch.charCodeAt(0); + return ch >= 48 && ch <= 57; }; function is_unicode_digit(ch) { - return UNICODE.digit.test(ch); + return UNICODE.digit.test(ch); } function is_alphanumeric_char(ch) { - return is_digit(ch) || is_letter(ch); + return is_digit(ch) || is_letter(ch); }; function is_unicode_combining_mark(ch) { - return UNICODE.combining_mark.test(ch); + return UNICODE.combining_mark.test(ch); }; function is_unicode_connector_punctuation(ch) { - return UNICODE.connector_punctuation.test(ch); + return UNICODE.connector_punctuation.test(ch); }; function is_identifier_start(ch) { - return ch == "$" || ch == "_" || is_letter(ch); + return ch == "$" || ch == "_" || is_letter(ch); }; function is_identifier_char(ch) { - return is_identifier_start(ch) - || is_unicode_combining_mark(ch) - || is_unicode_digit(ch) - || is_unicode_connector_punctuation(ch) - || ch == "\u200c" // zero-width non-joiner - || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) - ; + return is_identifier_start(ch) + || is_unicode_combining_mark(ch) + || is_unicode_digit(ch) + || is_unicode_connector_punctuation(ch) + || ch == "\u200c" // zero-width non-joiner + || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) + ; }; function parse_js_number(num) { - if (RE_HEX_NUMBER.test(num)) { - return parseInt(num.substr(2), 16); - } else if (RE_OCT_NUMBER.test(num)) { - return parseInt(num.substr(1), 8); - } else if (RE_DEC_NUMBER.test(num)) { - return parseFloat(num); - } + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } }; function JS_Parse_Error(message, line, col, pos) { - this.message = message; - this.line = line + 1; - this.col = col + 1; - this.pos = pos + 1; - this.stack = new Error().stack; + this.message = message; + this.line = line + 1; + this.col = col + 1; + this.pos = pos + 1; + this.stack = new Error().stack; }; JS_Parse_Error.prototype.toString = function() { - return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; }; function js_error(message, line, col, pos) { - throw new JS_Parse_Error(message, line, col, pos); + throw new JS_Parse_Error(message, line, col, pos); }; function is_token(token, type, val) { - return token.type == type && (val == null || token.value == val); + return token.type == type && (val == null || token.value == val); }; var EX_EOF = {}; function tokenizer($TEXT) { - var S = { - text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), - pos : 0, - tokpos : 0, - line : 0, - tokline : 0, - col : 0, - tokcol : 0, - newline_before : false, - regex_allowed : false, - comments_before : [] - }; - - function peek() { return S.text.charAt(S.pos); }; - - function next(signal_eof, in_string) { - var ch = S.text.charAt(S.pos++); - if (signal_eof && !ch) - throw EX_EOF; - if (ch == "\n") { - S.newline_before = S.newline_before || !in_string; - ++S.line; - S.col = 0; - } else { - ++S.col; - } - return ch; - }; - - function eof() { - return !S.peek(); - }; - - function find(what, signal_eof) { - var pos = S.text.indexOf(what, S.pos); - if (signal_eof && pos == -1) throw EX_EOF; - return pos; - }; - - function start_token() { - S.tokline = S.line; - S.tokcol = S.col; - S.tokpos = S.pos; - }; - - function token(type, value, is_comment) { - S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || - (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || - (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); - var ret = { - type : type, - value : value, - line : S.tokline, - col : S.tokcol, - pos : S.tokpos, - endpos : S.pos, - nlb : S.newline_before - }; - if (!is_comment) { - ret.comments_before = S.comments_before; - S.comments_before = []; - // make note of any newlines in the comments that came before - for (var i = 0, len = ret.comments_before.length; i < len; i++) { - ret.nlb = ret.nlb || ret.comments_before[i].nlb; - } - } - S.newline_before = false; - return ret; - }; - - function skip_whitespace() { - while (HOP(WHITESPACE_CHARS, peek())) - next(); - }; - - function read_while(pred) { - var ret = "", ch = peek(), i = 0; - while (ch && pred(ch, i++)) { - ret += next(); - ch = peek(); - } - return ret; - }; - - function parse_error(err) { - js_error(err, S.tokline, S.tokcol, S.tokpos); - }; - - function read_num(prefix) { - var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; - var num = read_while(function(ch, i){ - if (ch == "x" || ch == "X") { - if (has_x) return false; - return has_x = true; - } - if (!has_x && (ch == "E" || ch == "e")) { - if (has_e) return false; - return has_e = after_e = true; - } - if (ch == "-") { - if (after_e || (i == 0 && !prefix)) return true; - return false; - } - if (ch == "+") return after_e; - after_e = false; - if (ch == ".") { - if (!has_dot && !has_x && !has_e) - return has_dot = true; - return false; - } - return is_alphanumeric_char(ch); - }); - if (prefix) - num = prefix + num; - var valid = parse_js_number(num); - if (!isNaN(valid)) { - return token("num", valid); - } else { - parse_error("Invalid syntax: " + num); - } - }; - - function read_escaped_char(in_string) { - var ch = next(true, in_string); - switch (ch) { - case "n" : return "\n"; - case "r" : return "\r"; - case "t" : return "\t"; - case "b" : return "\b"; - case "v" : return "\u000b"; - case "f" : return "\f"; - case "0" : return "\0"; - case "x" : return String.fromCharCode(hex_bytes(2)); - case "u" : return String.fromCharCode(hex_bytes(4)); - case "\n": return ""; - default : return ch; - } - }; - - function hex_bytes(n) { - var num = 0; - for (; n > 0; --n) { - var digit = parseInt(next(true), 16); - if (isNaN(digit)) - parse_error("Invalid hex-character pattern in string"); - num = (num << 4) | digit; - } - return num; - }; - - function read_string() { - return with_eof_error("Unterminated string constant", function(){ - var quote = next(), ret = ""; - for (;;) { - var ch = next(true); - if (ch == "\\") { - // read OctalEscapeSequence (XXX: deprecated if "strict mode") - // https://github.com/mishoo/UglifyJS/issues/178 - var octal_len = 0, first = null; - ch = read_while(function(ch){ - if (ch >= "0" && ch <= "7") { - if (!first) { - first = ch; - return ++octal_len; - } - else if (first <= "3" && octal_len <= 2) return ++octal_len; - else if (first >= "4" && octal_len <= 1) return ++octal_len; - } - return false; - }); - if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); - else ch = read_escaped_char(true); - } - else if (ch == quote) break; - ret += ch; - } - return token("string", ret); - }); - }; - - function read_line_comment() { - next(); - var i = find("\n"), ret; - if (i == -1) { - ret = S.text.substr(S.pos); - S.pos = S.text.length; - } else { - ret = S.text.substring(S.pos, i); - S.pos = i; - } - return token("comment1", ret, true); - }; - - function read_multiline_comment() { - next(); - return with_eof_error("Unterminated multiline comment", function(){ - var i = find("*/", true), - text = S.text.substring(S.pos, i); - S.pos = i + 2; - S.line += text.split("\n").length - 1; - S.newline_before = S.newline_before || text.indexOf("\n") >= 0; - - // https://github.com/mishoo/UglifyJS/issues/#issue/100 - if (/^@cc_on/i.test(text)) { - warn("WARNING: at line " + S.line); - warn("*** Found \"conditional comment\": " + text); - warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); - } - - return token("comment2", text, true); - }); - }; - - function read_name() { - var backslash = false, name = "", ch, escaped = false, hex; - while ((ch = peek()) != null) { - if (!backslash) { - if (ch == "\\") escaped = backslash = true, next(); - else if (is_identifier_char(ch)) name += next(); - else break; - } - else { - if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); - ch = read_escaped_char(); - if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); - name += ch; - backslash = false; - } - } - if (HOP(KEYWORDS, name) && escaped) { - hex = name.charCodeAt(0).toString(16).toUpperCase(); - name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); - } - return name; - }; - - function read_regexp(regexp) { - return with_eof_error("Unterminated regular expression", function(){ - var prev_backslash = false, ch, in_class = false; - while ((ch = next(true))) if (prev_backslash) { - regexp += "\\" + ch; - prev_backslash = false; - } else if (ch == "[") { - in_class = true; - regexp += ch; - } else if (ch == "]" && in_class) { - in_class = false; - regexp += ch; - } else if (ch == "/" && !in_class) { - break; - } else if (ch == "\\") { - prev_backslash = true; - } else { - regexp += ch; - } - var mods = read_name(); - return token("regexp", [ regexp, mods ]); - }); - }; - - function read_operator(prefix) { - function grow(op) { - if (!peek()) return op; - var bigger = op + peek(); - if (HOP(OPERATORS, bigger)) { - next(); - return grow(bigger); - } else { - return op; + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), + pos : 0, + tokpos : 0, + line : 0, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function eof() { + return !S.peek(); + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || + (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || + (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return ret; + }; + + function skip_whitespace() { + while (HOP(WHITESPACE_CHARS, peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch = peek(), i = 0; + while (ch && pred(ch, i++)) { + ret += next(); + ch = peek(); + } + return ret; + }; + + function parse_error(err) { + js_error(err, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + if (ch == "x" || ch == "X") { + if (has_x) return false; + return has_x = true; + } + if (!has_x && (ch == "E" || ch == "e")) { + if (has_e) return false; + return has_e = after_e = true; + } + if (ch == "-") { + if (after_e || (i == 0 && !prefix)) return true; + return false; + } + if (ch == "+") return after_e; + after_e = false; + if (ch == ".") { + if (!has_dot && !has_x && !has_e) + return has_dot = true; + return false; + } + return is_alphanumeric_char(ch); + }); + if (prefix) + num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch) { + case "n" : return "\n"; + case "r" : return "\r"; + case "t" : return "\t"; + case "b" : return "\b"; + case "v" : return "\u000b"; + case "f" : return "\f"; + case "0" : return "\0"; + case "x" : return String.fromCharCode(hex_bytes(2)); + case "u" : return String.fromCharCode(hex_bytes(4)); + case "\n": return ""; + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + function read_string() { + return with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; } - }; - return token("operator", grow(prefix || next())); - }; - - function handle_slash() { - next(); - var regex_allowed = S.regex_allowed; - switch (peek()) { - case "/": - S.comments_before.push(read_line_comment()); - S.regex_allowed = regex_allowed; - return next_token(); - case "*": - S.comments_before.push(read_multiline_comment()); - S.regex_allowed = regex_allowed; - return next_token(); + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); } - return S.regex_allowed ? read_regexp("") : read_operator("/"); - }; + else if (ch == quote) break; + else if (ch == "\n") throw EX_EOF; + ret += ch; + } + return token("string", ret); + }); + }; + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + function read_multiline_comment() { + next(); + return with_eof_error("Unterminated multiline comment", function(){ + var i = find("*/", true), + text = S.text.substring(S.pos, i); + S.pos = i + 2; + S.line += text.split("\n").length - 1; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + + // https://github.com/mishoo/UglifyJS/issues/#issue/100 + if (/^@cc_on/i.test(text)) { + warn("WARNING: at line " + S.line); + warn("*** Found \"conditional comment\": " + text); + warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); + } + + return token("comment2", text, true); + }); + }; + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (HOP(KEYWORDS, name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + function read_regexp(regexp) { + return with_eof_error("Unterminated regular expression", function(){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", [ regexp, mods ]); + }); + }; - function handle_dot() { + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (HOP(OPERATORS, bigger)) { next(); - return is_digit(peek()) - ? read_num(".") - : token("punc", "."); - }; - - function read_word() { - var word = read_name(); - return !HOP(KEYWORDS, word) - ? token("name", word) - : HOP(OPERATORS, word) - ? token("operator", word) - : HOP(KEYWORDS_ATOM, word) - ? token("atom", word) - : token("keyword", word); - }; - - function with_eof_error(eof_error, cont) { - try { - return cont(); - } catch(ex) { - if (ex === EX_EOF) parse_error(eof_error); - else throw ex; - } - }; - - function next_token(force_regexp) { - if (force_regexp != null) - return read_regexp(force_regexp); - skip_whitespace(); - start_token(); - var ch = peek(); - if (!ch) return token("eof"); - if (is_digit(ch)) return read_num(); - if (ch == '"' || ch == "'") return read_string(); - if (HOP(PUNC_CHARS, ch)) return token("punc", next()); - if (ch == ".") return handle_dot(); - if (ch == "/") return handle_slash(); - if (HOP(OPERATOR_CHARS, ch)) return read_operator(); - if (ch == "\\" || is_identifier_start(ch)) return read_word(); - parse_error("Unexpected character '" + ch + "'"); - }; - - next_token.context = function(nc) { - if (nc) S = nc; - return S; - }; - - return next_token; + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek()) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return !HOP(KEYWORDS, word) + ? token("name", word) + : HOP(OPERATORS, word) + ? token("operator", word) + : HOP(KEYWORDS_ATOM, word) + ? token("atom", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + try { + return cont(); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + if (is_digit(ch)) return read_num(); + if (ch == '"' || ch == "'") return read_string(); + if (HOP(PUNC_CHARS, ch)) return token("punc", next()); + if (ch == ".") return handle_dot(); + if (ch == "/") return handle_slash(); + if (HOP(OPERATOR_CHARS, ch)) return read_operator(); + if (ch == "\\" || is_identifier_start(ch)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; }; /* -----[ Parser (constants) ]----- */ var UNARY_PREFIX = array_to_hash([ - "typeof", - "void", - "delete", - "--", - "++", - "!", - "~", - "-", - "+" + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" ]); var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); var ASSIGNMENT = (function(a, ret, i){ - while (i < a.length) { - ret[a[i]] = a[i].substr(0, a[i].length - 1); - i++; - } - return ret; + while (i < a.length) { + ret[a[i]] = a[i].substr(0, a[i].length - 1); + i++; + } + return ret; })( - ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], - { "=": true }, - 0 + ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], + { "=": true }, + 0 ); var PRECEDENCE = (function(a, ret){ - for (var i = 0, n = 1; i < a.length; ++i, ++n) { - var b = a[i]; - for (var j = 0; j < b.length; ++j) { - ret[b[j]] = n; - } + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; } - return ret; + } + return ret; })( - [ - ["||"], - ["&&"], - ["|"], - ["^"], - ["&"], - ["==", "===", "!=", "!=="], - ["<", ">", "<=", ">=", "in", "instanceof"], - [">>", "<<", ">>>"], - ["+", "-"], - ["*", "/", "%"] - ], - {} + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} ); var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); @@ -681,663 +682,663 @@ var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "nam /* -----[ Parser ]----- */ function NodeWithToken(str, start, end) { - this.name = str; - this.start = start; - this.end = end; + this.name = str; + this.start = start; + this.end = end; }; NodeWithToken.prototype.toString = function() { return this.name; }; function parse($TEXT, exigent_mode, embed_tokens) { - var S = { - input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, - token : null, - prev : null, - peeked : null, - in_function : 0, - in_directives : true, - in_loop : 0, - labels : [] - }; - - S.token = next(); - - function is(type, value) { - return is_token(S.token, type, value); - }; - - function peek() { return S.peeked || (S.peeked = S.input()); }; - - function next() { - S.prev = S.token; - if (S.peeked) { - S.token = S.peeked; - S.peeked = null; - } else { - S.token = S.input(); - } - S.in_directives = S.in_directives && ( - S.token.type == "string" || is("punc", ";") - ); - return S.token; - }; - - function prev() { - return S.prev; - }; - - function croak(msg, line, col, pos) { - var ctx = S.input.context(); - js_error(msg, - line != null ? line : ctx.tokline, - col != null ? col : ctx.tokcol, - pos != null ? pos : ctx.tokpos); - }; - - function token_error(token, msg) { - croak(msg, token.line, token.col); - }; - - function unexpected(token) { - if (token == null) - token = S.token; - token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); - }; - - function expect_token(type, val) { - if (is(type, val)) { - return next(); - } - token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); - }; - - function expect(punc) { return expect_token("punc", punc); }; - - function can_insert_semicolon() { - return !exigent_mode && ( - S.token.nlb || is("eof") || is("punc", "}") - ); - }; - - function semicolon() { - if (is("punc", ";")) next(); - else if (!can_insert_semicolon()) unexpected(); - }; - - function as() { - return slice(arguments); - }; - - function parenthesised() { - expect("("); - var ex = expression(); - expect(")"); - return ex; - }; - - function add_tokens(str, start, end) { - return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); - }; - - function maybe_embed_tokens(parser) { - if (embed_tokens) return function() { - var start = S.token; - var ast = parser.apply(this, arguments); - ast[0] = add_tokens(ast[0], start, prev()); - return ast; - }; - else return parser; - }; - - var statement = maybe_embed_tokens(function() { - if (is("operator", "/") || is("operator", "/=")) { - S.peeked = null; - S.token = S.input(S.token.value.substr(1)); // force regexp - } - switch (S.token.type) { - case "string": - var dir = S.in_directives, stat = simple_statement(); - if (dir && stat[1][0] == "string" && !is("punc", ",")) - return as("directive", stat[1][1]); - return stat; - case "num": - case "regexp": - case "operator": - case "atom": - return simple_statement(); - - case "name": - return is_token(peek(), "punc", ":") - ? labeled_statement(prog1(S.token.value, next, next)) - : simple_statement(); - - case "punc": - switch (S.token.value) { - case "{": - return as("block", block_()); - case "[": - case "(": - return simple_statement(); - case ";": - next(); - return as("block"); - default: - unexpected(); - } - - case "keyword": - switch (prog1(S.token.value, next)) { - case "break": - return break_cont("break"); - - case "continue": - return break_cont("continue"); - - case "debugger": - semicolon(); - return as("debugger"); - - case "do": - return (function(body){ - expect_token("keyword", "while"); - return as("do", prog1(parenthesised, semicolon), body); - })(in_loop(statement)); - - case "for": - return for_(); - - case "function": - return function_(true); - - case "if": - return if_(); - - case "return": - if (S.in_function == 0) - croak("'return' outside of function"); - return as("return", - is("punc", ";") - ? (next(), null) - : can_insert_semicolon() - ? null - : prog1(expression, semicolon)); + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !exigent_mode && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function as() { + return slice(arguments); + }; + + function parenthesised() { + expect("("); + var ex = expression(); + expect(")"); + return ex; + }; + + function add_tokens(str, start, end) { + return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); + }; + + function maybe_embed_tokens(parser) { + if (embed_tokens) return function() { + var start = S.token; + var ast = parser.apply(this, arguments); + ast[0] = add_tokens(ast[0], start, prev()); + return ast; + }; + else return parser; + }; + + var statement = maybe_embed_tokens(function() { + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + if (dir && stat[1][0] == "string" && !is("punc", ",")) + return as("directive", stat[1][1]); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement(prog1(S.token.value, next, next)) + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return as("block", block_()); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return as("block"); + default: + unexpected(); + } - case "switch": - return as("switch", parenthesised(), switch_block_()); + case "keyword": + switch (prog1(S.token.value, next)) { + case "break": + return break_cont("break"); - case "throw": - if (S.token.nlb) - croak("Illegal newline after 'throw'"); - return as("throw", prog1(expression, semicolon)); + case "continue": + return break_cont("continue"); - case "try": - return try_(); + case "debugger": + semicolon(); + return as("debugger"); - case "var": - return prog1(var_, semicolon); + case "do": + return (function(body){ + expect_token("keyword", "while"); + return as("do", prog1(parenthesised, semicolon), body); + })(in_loop(statement)); - case "const": - return prog1(const_, semicolon); + case "for": + return for_(); - case "while": - return as("while", parenthesised(), in_loop(statement)); + case "function": + return function_(true); - case "with": - return as("with", parenthesised(), statement()); + case "if": + return if_(); - default: - unexpected(); - } - } - }); + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return as("return", + is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : prog1(expression, semicolon)); - function labeled_statement(label) { - S.labels.push(label); - var start = S.token, stat = statement(); - if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) - unexpected(start); - S.labels.pop(); - return as("label", label, stat); - }; - - function simple_statement() { - return as("stat", prog1(expression, semicolon)); - }; + case "switch": + return as("switch", parenthesised(), switch_block_()); - function break_cont(type) { - var name; - if (!can_insert_semicolon()) { - name = is("name") ? S.token.value : null; - } - if (name != null) { - next(); - if (!member(name, S.labels)) - croak("Label " + name + " without matching loop or statement"); - } - else if (S.in_loop == 0) - croak(type + " not inside a loop or switch"); - semicolon(); - return as(type, name); - }; + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return as("throw", prog1(expression, semicolon)); - function for_() { - expect("("); - var init = null; - if (!is("punc", ";")) { - init = is("keyword", "var") - ? (next(), var_(true)) - : expression(true, true); - if (is("operator", "in")) { - if (init[0] == "var" && init[1].length > 1) - croak("Only one variable declaration allowed in for..in loop"); - return for_in(init); - } - } - return regular_for(init); - }; + case "try": + return try_(); - function regular_for(init) { - expect(";"); - var test = is("punc", ";") ? null : expression(); - expect(";"); - var step = is("punc", ")") ? null : expression(); - expect(")"); - return as("for", init, test, step, in_loop(statement)); - }; + case "var": + return prog1(var_, semicolon); - function for_in(init) { - var lhs = init[0] == "var" ? as("name", init[1][0]) : init; - next(); - var obj = expression(); - expect(")"); - return as("for-in", init, lhs, obj, in_loop(statement)); - }; + case "const": + return prog1(const_, semicolon); - var function_ = function(in_statement) { - var name = is("name") ? prog1(S.token.value, next) : null; - if (in_statement && !name) - unexpected(); - expect("("); - return as(in_statement ? "defun" : "function", - name, - // arguments - (function(first, a){ - while (!is("punc", ")")) { - if (first) first = false; else expect(","); - if (!is("name")) unexpected(); - a.push(S.token.value); - next(); - } - next(); - return a; - })(true, []), - // body - (function(){ - ++S.in_function; - var loop = S.in_loop; - S.in_directives = true; - S.in_loop = 0; - var a = block_(); - --S.in_function; - S.in_loop = loop; - return a; - })()); - }; + case "while": + return as("while", parenthesised(), in_loop(statement)); - function if_() { - var cond = parenthesised(), body = statement(), belse; - if (is("keyword", "else")) { - next(); - belse = statement(); - } - return as("if", cond, body, belse); - }; + case "with": + return as("with", parenthesised(), statement()); - function block_() { - expect("{"); - var a = []; - while (!is("punc", "}")) { - if (is("eof")) unexpected(); - a.push(statement()); - } + default: + unexpected(); + } + } + }); + + function labeled_statement(label) { + S.labels.push(label); + var start = S.token, stat = statement(); + if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) + unexpected(start); + S.labels.pop(); + return as("label", label, stat); + }; + + function simple_statement() { + return as("stat", prog1(expression, semicolon)); + }; + + function break_cont(type) { + var name; + if (!can_insert_semicolon()) { + name = is("name") ? S.token.value : null; + } + if (name != null) { + next(); + if (!member(name, S.labels)) + croak("Label " + name + " without matching loop or statement"); + } + else if (S.in_loop == 0) + croak(type + " not inside a loop or switch"); + semicolon(); + return as(type, name); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init[0] == "var" && init[1].length > 1) + croak("Only one variable declaration allowed in for..in loop"); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(); + expect(";"); + var step = is("punc", ")") ? null : expression(); + expect(")"); + return as("for", init, test, step, in_loop(statement)); + }; + + function for_in(init) { + var lhs = init[0] == "var" ? as("name", init[1][0]) : init; + next(); + var obj = expression(); + expect(")"); + return as("for-in", init, lhs, obj, in_loop(statement)); + }; + + var function_ = function(in_statement) { + var name = is("name") ? prog1(S.token.value, next) : null; + if (in_statement && !name) + unexpected(); + expect("("); + return as(in_statement ? "defun" : "function", + name, + // arguments + (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + if (!is("name")) unexpected(); + a.push(S.token.value); + next(); + } + next(); + return a; + })(true, []), + // body + (function(){ + ++S.in_function; + var loop = S.in_loop; + S.in_directives = true; + S.in_loop = 0; + var a = block_(); + --S.in_function; + S.in_loop = loop; + return a; + })()); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return as("if", cond, body, belse); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + var switch_block_ = curry(in_loop, function(){ + expect("{"); + var a = [], cur = null; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { next(); - return a; - }; - - var switch_block_ = curry(in_loop, function(){ - expect("{"); - var a = [], cur = null; - while (!is("punc", "}")) { - if (is("eof")) unexpected(); - if (is("keyword", "case")) { - next(); - cur = []; - a.push([ expression(), cur ]); - expect(":"); - } - else if (is("keyword", "default")) { - next(); - expect(":"); - cur = []; - a.push([ null, cur ]); - } - else { - if (!cur) unexpected(); - cur.push(statement()); - } - } + cur = []; + a.push([ expression(), cur ]); + expect(":"); + } + else if (is("keyword", "default")) { next(); - return a; - }); - - function try_() { - var body = block_(), bcatch, bfinally; - if (is("keyword", "catch")) { - next(); - expect("("); - if (!is("name")) - croak("Name expected"); - var name = S.token.value; - next(); - expect(")"); - bcatch = [ name, block_() ]; - } - if (is("keyword", "finally")) { - next(); - bfinally = block_(); - } - if (!bcatch && !bfinally) - croak("Missing catch/finally blocks"); - return as("try", body, bcatch, bfinally); - }; - - function vardefs(no_in) { - var a = []; - for (;;) { - if (!is("name")) - unexpected(); - var name = S.token.value; - next(); - if (is("operator", "=")) { - next(); - a.push([ name, expression(false, no_in) ]); - } else { - a.push([ name ]); - } - if (!is("punc", ",")) - break; - next(); - } - return a; - }; - - function var_(no_in) { - return as("var", vardefs(no_in)); - }; - - function const_() { - return as("const", vardefs()); - }; - - function new_() { - var newexp = expr_atom(false), args; - if (is("punc", "(")) { - next(); - args = expr_list(")"); - } else { - args = []; - } - return subscripts(as("new", newexp, args), true); - }; - - var expr_atom = maybe_embed_tokens(function(allow_calls) { - if (is("operator", "new")) { - next(); - return new_(); - } - if (is("punc")) { - switch (S.token.value) { - case "(": - next(); - return subscripts(prog1(expression, curry(expect, ")")), allow_calls); - case "[": - next(); - return subscripts(array_(), allow_calls); - case "{": - next(); - return subscripts(object_(), allow_calls); - } - unexpected(); - } - if (is("keyword", "function")) { - next(); - return subscripts(function_(false), allow_calls); - } - if (HOP(ATOMIC_START_TOKEN, S.token.type)) { - var atom = S.token.type == "regexp" - ? as("regexp", S.token.value[0], S.token.value[1]) - : as(S.token.type, S.token.value); - return subscripts(prog1(atom, next), allow_calls); - } + expect(":"); + cur = []; + a.push([ null, cur ]); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + next(); + return a; + }); + + function try_() { + var body = block_(), bcatch, bfinally; + if (is("keyword", "catch")) { + next(); + expect("("); + if (!is("name")) + croak("Name expected"); + var name = S.token.value; + next(); + expect(")"); + bcatch = [ name, block_() ]; + } + if (is("keyword", "finally")) { + next(); + bfinally = block_(); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return as("try", body, bcatch, bfinally); + }; + + function vardefs(no_in) { + var a = []; + for (;;) { + if (!is("name")) unexpected(); - }); - - function expr_list(closing, allow_trailing_comma, allow_empty) { - var first = true, a = []; - while (!is("punc", closing)) { - if (first) first = false; else expect(","); - if (allow_trailing_comma && is("punc", closing)) break; - if (is("punc", ",") && allow_empty) { - a.push([ "atom", "undefined" ]); - } else { - a.push(expression(false)); - } - } + var name = S.token.value; + next(); + if (is("operator", "=")) { next(); - return a; - }; - - function array_() { - return as("array", expr_list("]", !exigent_mode, true)); - }; + a.push([ name, expression(false, no_in) ]); + } else { + a.push([ name ]); + } + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + function var_(no_in) { + return as("var", vardefs(no_in)); + }; + + function const_() { + return as("const", vardefs()); + }; + + function new_() { + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(as("new", newexp, args), true); + }; - function object_() { - var first = true, a = []; - while (!is("punc", "}")) { - if (first) first = false; else expect(","); - if (!exigent_mode && is("punc", "}")) - // allow trailing comma - break; - var type = S.token.type; - var name = as_property_name(); - if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { - a.push([ as_name(), function_(false), name ]); - } else { - expect(":"); - a.push([ name, expression(false) ]); - } - } + var expr_atom = maybe_embed_tokens(function(allow_calls) { + if (is("operator", "new")) { + next(); + return new_(); + } + if (is("punc")) { + switch (S.token.value) { + case "(": next(); - return as("object", a); - }; - - function as_property_name() { - switch (S.token.type) { - case "num": - case "string": - return prog1(S.token.value, next); - } - return as_name(); - }; - - function as_name() { - switch (S.token.type) { - case "name": - case "operator": - case "keyword": - case "atom": - return prog1(S.token.value, next); - default: - unexpected(); - } - }; - - function subscripts(expr, allow_calls) { - if (is("punc", ".")) { - next(); - return subscripts(as("dot", expr, as_name()), allow_calls); - } - if (is("punc", "[")) { - next(); - return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); - } - if (allow_calls && is("punc", "(")) { - next(); - return subscripts(as("call", expr, expr_list(")")), true); - } - return expr; - }; - - function maybe_unary(allow_calls) { - if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { - return make_unary("unary-prefix", - prog1(S.token.value, next), - maybe_unary(allow_calls)); - } - var val = expr_atom(allow_calls); - while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) { - val = make_unary("unary-postfix", S.token.value, val); - next(); - } - return val; - }; - - function make_unary(tag, op, expr) { - if ((op == "++" || op == "--") && !is_assignable(expr)) - croak("Invalid use of " + op + " operator"); - return as(tag, op, expr); - }; - - function expr_op(left, min_prec, no_in) { - var op = is("operator") ? S.token.value : null; - if (op && op == "in" && no_in) op = null; - var prec = op != null ? PRECEDENCE[op] : null; - if (prec != null && prec > min_prec) { - next(); - var right = expr_op(maybe_unary(true), prec, no_in); - return expr_op(as("binary", op, left, right), min_prec, no_in); - } - return left; - }; - - function expr_ops(no_in) { - return expr_op(maybe_unary(true), 0, no_in); - }; - - function maybe_conditional(no_in) { - var expr = expr_ops(no_in); - if (is("operator", "?")) { - next(); - var yes = expression(false); - expect(":"); - return as("conditional", expr, yes, expression(false, no_in)); - } - return expr; - }; - - function is_assignable(expr) { - if (!exigent_mode) return true; - switch (expr[0]+"") { - case "dot": - case "sub": - case "new": - case "call": - return true; - case "name": - return expr[1] != "this"; - } - }; - - function maybe_assign(no_in) { - var left = maybe_conditional(no_in), val = S.token.value; - if (is("operator") && HOP(ASSIGNMENT, val)) { - if (is_assignable(left)) { - next(); - return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); - } - croak("Invalid assignment"); - } - return left; - }; + return subscripts(prog1(expression, curry(expect, ")")), allow_calls); + case "[": + next(); + return subscripts(array_(), allow_calls); + case "{": + next(); + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + return subscripts(function_(false), allow_calls); + } + if (HOP(ATOMIC_START_TOKEN, S.token.type)) { + var atom = S.token.type == "regexp" + ? as("regexp", S.token.value[0], S.token.value[1]) + : as(S.token.type, S.token.value); + return subscripts(prog1(atom, next), allow_calls); + } + unexpected(); + }); + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push([ "atom", "undefined" ]); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + function array_() { + return as("array", expr_list("]", !exigent_mode, true)); + }; + + function object_() { + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!exigent_mode && is("punc", "}")) + // allow trailing comma + break; + var type = S.token.type; + var name = as_property_name(); + if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { + a.push([ as_name(), function_(false), name ]); + } else { + expect(":"); + a.push([ name, expression(false) ]); + } + } + next(); + return as("object", a); + }; + + function as_property_name() { + switch (S.token.type) { + case "num": + case "string": + return prog1(S.token.value, next); + } + return as_name(); + }; + + function as_name() { + switch (S.token.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return prog1(S.token.value, next); + default: + unexpected(); + } + }; - var expression = maybe_embed_tokens(function(commas, no_in) { - if (arguments.length == 0) - commas = true; - var expr = maybe_assign(no_in); - if (commas && is("punc", ",")) { - next(); - return as("seq", expr, expression(true, no_in)); - } - return expr; - }); + function subscripts(expr, allow_calls) { + if (is("punc", ".")) { + next(); + return subscripts(as("dot", expr, as_name()), allow_calls); + } + if (is("punc", "[")) { + next(); + return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(as("call", expr, expr_list(")")), true); + } + return expr; + }; + + function maybe_unary(allow_calls) { + if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { + return make_unary("unary-prefix", + prog1(S.token.value, next), + maybe_unary(allow_calls)); + } + var val = expr_atom(allow_calls); + while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) { + val = make_unary("unary-postfix", S.token.value, val); + next(); + } + return val; + }; + + function make_unary(tag, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return as(tag, op, expr); + }; + + function expr_op(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op && op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(as("binary", op, left, right), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + function maybe_conditional(no_in) { + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return as("conditional", expr, yes, expression(false, no_in)); + } + return expr; + }; + + function is_assignable(expr) { + if (!exigent_mode) return true; + switch (expr[0]+"") { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; - function in_loop(cont) { - try { - ++S.in_loop; - return cont(); - } finally { - --S.in_loop; - } - }; + function maybe_assign(no_in) { + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && HOP(ASSIGNMENT, val)) { + if (is_assignable(left)) { + next(); + return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = maybe_embed_tokens(function(commas, no_in) { + if (arguments.length == 0) + commas = true; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return as("seq", expr, expression(true, no_in)); + } + return expr; + }); + + function in_loop(cont) { + try { + ++S.in_loop; + return cont(); + } finally { + --S.in_loop; + } + }; - return as("toplevel", (function(a){ - while (!is("eof")) - a.push(statement()); - return a; - })([])); + return as("toplevel", (function(a){ + while (!is("eof")) + a.push(statement()); + return a; + })([])); }; /* -----[ Utilities ]----- */ function curry(f) { - var args = slice(arguments, 1); - return function() { return f.apply(this, args.concat(slice(arguments))); }; + var args = slice(arguments, 1); + return function() { return f.apply(this, args.concat(slice(arguments))); }; }; function prog1(ret) { - if (ret instanceof Function) - ret = ret(); - for (var i = 1, n = arguments.length; --n > 0; ++i) - arguments[i](); - return ret; + if (ret instanceof Function) + ret = ret(); + for (var i = 1, n = arguments.length; --n > 0; ++i) + arguments[i](); + return ret; }; function array_to_hash(a) { - var ret = {}; - for (var i = 0; i < a.length; ++i) - ret[a[i]] = true; - return ret; + var ret = {}; + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; }; function slice(a, start) { - return Array.prototype.slice.call(a, start || 0); + return Array.prototype.slice.call(a, start || 0); }; function characters(str) { - return str.split(""); + return str.split(""); }; function member(name, array) { - for (var i = array.length; --i >= 0;) - if (array[i] == name) - return true; - return false; + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; }; function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); + return Object.prototype.hasOwnProperty.call(obj, prop); }; var warn = function() {}; @@ -1360,9 +1361,9 @@ exports.is_alphanumeric_char = is_alphanumeric_char; exports.is_identifier_start = is_identifier_start; exports.is_identifier_char = is_identifier_char; exports.set_logger = function(logger) { - warn = logger; + warn = logger; }; // Local variables: -// js-indent-level: 8 +// js-indent-level: 4 // End: diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/process.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/process.js index 640d9e2..42d61df 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/process.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/process.js @@ -69,574 +69,574 @@ var jsp = require("./parse-js"), /* -----[ helper for AST traversal ]----- */ function ast_walker() { - function _vardefs(defs) { - return [ this[0], MAP(defs, function(def){ - var a = [ def[0] ]; - if (def.length > 1) - a[1] = walk(def[1]); - return a; - }) ]; - }; - function _block(statements) { - var out = [ this[0] ]; - if (statements != null) - out.push(MAP(statements, walk)); - return out; - }; - var walkers = { - "string": function(str) { - return [ this[0], str ]; - }, - "num": function(num) { - return [ this[0], num ]; - }, - "name": function(name) { - return [ this[0], name ]; - }, - "toplevel": function(statements) { - return [ this[0], MAP(statements, walk) ]; - }, - "block": _block, - "splice": _block, - "var": _vardefs, - "const": _vardefs, - "try": function(t, c, f) { - return [ - this[0], - MAP(t, walk), - c != null ? [ c[0], MAP(c[1], walk) ] : null, - f != null ? MAP(f, walk) : null - ]; - }, - "throw": function(expr) { - return [ this[0], walk(expr) ]; - }, - "new": function(ctor, args) { - return [ this[0], walk(ctor), MAP(args, walk) ]; - }, - "switch": function(expr, body) { - return [ this[0], walk(expr), MAP(body, function(branch){ - return [ branch[0] ? walk(branch[0]) : null, - MAP(branch[1], walk) ]; - }) ]; - }, - "break": function(label) { - return [ this[0], label ]; - }, - "continue": function(label) { - return [ this[0], label ]; - }, - "conditional": function(cond, t, e) { - return [ this[0], walk(cond), walk(t), walk(e) ]; - }, - "assign": function(op, lvalue, rvalue) { - return [ this[0], op, walk(lvalue), walk(rvalue) ]; - }, - "dot": function(expr) { - return [ this[0], walk(expr) ].concat(slice(arguments, 1)); - }, - "call": function(expr, args) { - return [ this[0], walk(expr), MAP(args, walk) ]; - }, - "function": function(name, args, body) { - return [ this[0], name, args.slice(), MAP(body, walk) ]; - }, - "debugger": function() { - return [ this[0] ]; - }, - "defun": function(name, args, body) { - return [ this[0], name, args.slice(), MAP(body, walk) ]; - }, - "if": function(conditional, t, e) { - return [ this[0], walk(conditional), walk(t), walk(e) ]; - }, - "for": function(init, cond, step, block) { - return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; - }, - "for-in": function(vvar, key, hash, block) { - return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; - }, - "while": function(cond, block) { - return [ this[0], walk(cond), walk(block) ]; - }, - "do": function(cond, block) { - return [ this[0], walk(cond), walk(block) ]; - }, - "return": function(expr) { - return [ this[0], walk(expr) ]; - }, - "binary": function(op, left, right) { - return [ this[0], op, walk(left), walk(right) ]; - }, - "unary-prefix": function(op, expr) { - return [ this[0], op, walk(expr) ]; - }, - "unary-postfix": function(op, expr) { - return [ this[0], op, walk(expr) ]; - }, - "sub": function(expr, subscript) { - return [ this[0], walk(expr), walk(subscript) ]; - }, - "object": function(props) { - return [ this[0], MAP(props, function(p){ - return p.length == 2 - ? [ p[0], walk(p[1]) ] - : [ p[0], walk(p[1]), p[2] ]; // get/set-ter - }) ]; - }, - "regexp": function(rx, mods) { - return [ this[0], rx, mods ]; - }, - "array": function(elements) { - return [ this[0], MAP(elements, walk) ]; - }, - "stat": function(stat) { - return [ this[0], walk(stat) ]; - }, - "seq": function() { - return [ this[0] ].concat(MAP(slice(arguments), walk)); - }, - "label": function(name, block) { - return [ this[0], name, walk(block) ]; - }, - "with": function(expr, block) { - return [ this[0], walk(expr), walk(block) ]; - }, - "atom": function(name) { - return [ this[0], name ]; - }, - "directive": function(dir) { - return [ this[0], dir ]; - } - }; - - var user = {}; - var stack = []; - function walk(ast) { - if (ast == null) - return null; - try { - stack.push(ast); - var type = ast[0]; - var gen = user[type]; - if (gen) { - var ret = gen.apply(ast, ast.slice(1)); - if (ret != null) - return ret; - } - gen = walkers[type]; - return gen.apply(ast, ast.slice(1)); - } finally { - stack.pop(); - } - }; - - function dive(ast) { - if (ast == null) - return null; - try { - stack.push(ast); - return walkers[ast[0]].apply(ast, ast.slice(1)); - } finally { - stack.pop(); - } - }; - - function with_walkers(walkers, cont){ - var save = {}, i; - for (i in walkers) if (HOP(walkers, i)) { - save[i] = user[i]; - user[i] = walkers[i]; - } - var ret = cont(); - for (i in save) if (HOP(save, i)) { - if (!save[i]) delete user[i]; - else user[i] = save[i]; - } - return ret; - }; + function _vardefs(defs) { + return [ this[0], MAP(defs, function(def){ + var a = [ def[0] ]; + if (def.length > 1) + a[1] = walk(def[1]); + return a; + }) ]; + }; + function _block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(MAP(statements, walk)); + return out; + }; + var walkers = { + "string": function(str) { + return [ this[0], str ]; + }, + "num": function(num) { + return [ this[0], num ]; + }, + "name": function(name) { + return [ this[0], name ]; + }, + "toplevel": function(statements) { + return [ this[0], MAP(statements, walk) ]; + }, + "block": _block, + "splice": _block, + "var": _vardefs, + "const": _vardefs, + "try": function(t, c, f) { + return [ + this[0], + MAP(t, walk), + c != null ? [ c[0], MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null + ]; + }, + "throw": function(expr) { + return [ this[0], walk(expr) ]; + }, + "new": function(ctor, args) { + return [ this[0], walk(ctor), MAP(args, walk) ]; + }, + "switch": function(expr, body) { + return [ this[0], walk(expr), MAP(body, function(branch){ + return [ branch[0] ? walk(branch[0]) : null, + MAP(branch[1], walk) ]; + }) ]; + }, + "break": function(label) { + return [ this[0], label ]; + }, + "continue": function(label) { + return [ this[0], label ]; + }, + "conditional": function(cond, t, e) { + return [ this[0], walk(cond), walk(t), walk(e) ]; + }, + "assign": function(op, lvalue, rvalue) { + return [ this[0], op, walk(lvalue), walk(rvalue) ]; + }, + "dot": function(expr) { + return [ this[0], walk(expr) ].concat(slice(arguments, 1)); + }, + "call": function(expr, args) { + return [ this[0], walk(expr), MAP(args, walk) ]; + }, + "function": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "debugger": function() { + return [ this[0] ]; + }, + "defun": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "if": function(conditional, t, e) { + return [ this[0], walk(conditional), walk(t), walk(e) ]; + }, + "for": function(init, cond, step, block) { + return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; + }, + "for-in": function(vvar, key, hash, block) { + return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; + }, + "while": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "do": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "return": function(expr) { + return [ this[0], walk(expr) ]; + }, + "binary": function(op, left, right) { + return [ this[0], op, walk(left), walk(right) ]; + }, + "unary-prefix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "unary-postfix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "sub": function(expr, subscript) { + return [ this[0], walk(expr), walk(subscript) ]; + }, + "object": function(props) { + return [ this[0], MAP(props, function(p){ + return p.length == 2 + ? [ p[0], walk(p[1]) ] + : [ p[0], walk(p[1]), p[2] ]; // get/set-ter + }) ]; + }, + "regexp": function(rx, mods) { + return [ this[0], rx, mods ]; + }, + "array": function(elements) { + return [ this[0], MAP(elements, walk) ]; + }, + "stat": function(stat) { + return [ this[0], walk(stat) ]; + }, + "seq": function() { + return [ this[0] ].concat(MAP(slice(arguments), walk)); + }, + "label": function(name, block) { + return [ this[0], name, walk(block) ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), walk(block) ]; + }, + "atom": function(name) { + return [ this[0], name ]; + }, + "directive": function(dir) { + return [ this[0], dir ]; + } + }; + + var user = {}; + var stack = []; + function walk(ast) { + if (ast == null) + return null; + try { + stack.push(ast); + var type = ast[0]; + var gen = user[type]; + if (gen) { + var ret = gen.apply(ast, ast.slice(1)); + if (ret != null) + return ret; + } + gen = walkers[type]; + return gen.apply(ast, ast.slice(1)); + } finally { + stack.pop(); + } + }; + + function dive(ast) { + if (ast == null) + return null; + try { + stack.push(ast); + return walkers[ast[0]].apply(ast, ast.slice(1)); + } finally { + stack.pop(); + } + }; - return { - walk: walk, - dive: dive, - with_walkers: with_walkers, - parent: function() { - return stack[stack.length - 2]; // last one is current node - }, - stack: function() { - return stack; - } - }; + function with_walkers(walkers, cont){ + var save = {}, i; + for (i in walkers) if (HOP(walkers, i)) { + save[i] = user[i]; + user[i] = walkers[i]; + } + var ret = cont(); + for (i in save) if (HOP(save, i)) { + if (!save[i]) delete user[i]; + else user[i] = save[i]; + } + return ret; + }; + + return { + walk: walk, + dive: dive, + with_walkers: with_walkers, + parent: function() { + return stack[stack.length - 2]; // last one is current node + }, + stack: function() { + return stack; + } + }; }; /* -----[ Scope and mangling ]----- */ function Scope(parent) { - this.names = {}; // names defined in this scope - this.mangled = {}; // mangled names (orig.name => mangled) - this.rev_mangled = {}; // reverse lookup (mangled => orig.name) - this.cname = -1; // current mangled name - this.refs = {}; // names referenced from this scope - this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes - this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes - this.directives = []; // directives activated from this scope - this.parent = parent; // parent scope - this.children = []; // sub-scopes - if (parent) { - this.level = parent.level + 1; - parent.children.push(this); - } else { - this.level = 0; - } + this.names = {}; // names defined in this scope + this.mangled = {}; // mangled names (orig.name => mangled) + this.rev_mangled = {}; // reverse lookup (mangled => orig.name) + this.cname = -1; // current mangled name + this.refs = {}; // names referenced from this scope + this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes + this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes + this.directives = []; // directives activated from this scope + this.parent = parent; // parent scope + this.children = []; // sub-scopes + if (parent) { + this.level = parent.level + 1; + parent.children.push(this); + } else { + this.level = 0; + } }; function base54_digits() { - if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined") - return DIGITS_OVERRIDE_FOR_TESTING; - else - return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984"; + if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined") + return DIGITS_OVERRIDE_FOR_TESTING; + else + return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984"; } var base54 = (function(){ - var DIGITS = base54_digits(); - return function(num) { - var ret = "", base = 54; - do { - ret += DIGITS.charAt(num % base); - num = Math.floor(num / base); - base = 64; - } while (num > 0); - return ret; - }; + var DIGITS = base54_digits(); + return function(num) { + var ret = "", base = 54; + do { + ret += DIGITS.charAt(num % base); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; })(); Scope.prototype = { - has: function(name) { - for (var s = this; s; s = s.parent) - if (HOP(s.names, name)) - return s; - }, - has_mangled: function(mname) { - for (var s = this; s; s = s.parent) - if (HOP(s.rev_mangled, mname)) - return s; - }, - toJSON: function() { - return { - names: this.names, - uses_eval: this.uses_eval, - uses_with: this.uses_with - }; - }, - - next_mangled: function() { - // we must be careful that the new mangled name: - // - // 1. doesn't shadow a mangled name from a parent - // scope, unless we don't reference the original - // name from this scope OR from any sub-scopes! - // This will get slow. - // - // 2. doesn't shadow an original name from a parent - // scope, in the event that the name is not mangled - // in the parent scope and we reference that name - // here OR IN ANY SUBSCOPES! - // - // 3. doesn't shadow a name that is referenced but not - // defined (possibly global defined elsewhere). - for (;;) { - var m = base54(++this.cname), prior; - - // case 1. - prior = this.has_mangled(m); - if (prior && this.refs[prior.rev_mangled[m]] === prior) - continue; - - // case 2. - prior = this.has(m); - if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) - continue; - - // case 3. - if (HOP(this.refs, m) && this.refs[m] == null) - continue; - - // I got "do" once. :-/ - if (!is_identifier(m)) - continue; - - return m; - } - }, - set_mangle: function(name, m) { - this.rev_mangled[m] = name; - return this.mangled[name] = m; - }, - get_mangled: function(name, newMangle) { - if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use - var s = this.has(name); - if (!s) return name; // not in visible scope, no mangle - if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope - if (!newMangle) return name; // not found and no mangling requested - return s.set_mangle(name, s.next_mangled()); - }, - references: function(name) { - return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name]; - }, - define: function(name, type) { - if (name != null) { - if (type == "var" || !HOP(this.names, name)) - this.names[name] = type || "var"; - return name; - } - }, - active_directive: function(dir) { - return member(dir, this.directives) || this.parent && this.parent.active_directive(dir); + has: function(name) { + for (var s = this; s; s = s.parent) + if (HOP(s.names, name)) + return s; + }, + has_mangled: function(mname) { + for (var s = this; s; s = s.parent) + if (HOP(s.rev_mangled, mname)) + return s; + }, + toJSON: function() { + return { + names: this.names, + uses_eval: this.uses_eval, + uses_with: this.uses_with + }; + }, + + next_mangled: function() { + // we must be careful that the new mangled name: + // + // 1. doesn't shadow a mangled name from a parent + // scope, unless we don't reference the original + // name from this scope OR from any sub-scopes! + // This will get slow. + // + // 2. doesn't shadow an original name from a parent + // scope, in the event that the name is not mangled + // in the parent scope and we reference that name + // here OR IN ANY SUBSCOPES! + // + // 3. doesn't shadow a name that is referenced but not + // defined (possibly global defined elsewhere). + for (;;) { + var m = base54(++this.cname), prior; + + // case 1. + prior = this.has_mangled(m); + if (prior && this.refs[prior.rev_mangled[m]] === prior) + continue; + + // case 2. + prior = this.has(m); + if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) + continue; + + // case 3. + if (HOP(this.refs, m) && this.refs[m] == null) + continue; + + // I got "do" once. :-/ + if (!is_identifier(m)) + continue; + + return m; } + }, + set_mangle: function(name, m) { + this.rev_mangled[m] = name; + return this.mangled[name] = m; + }, + get_mangled: function(name, newMangle) { + if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use + var s = this.has(name); + if (!s) return name; // not in visible scope, no mangle + if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope + if (!newMangle) return name; // not found and no mangling requested + return s.set_mangle(name, s.next_mangled()); + }, + references: function(name) { + return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name]; + }, + define: function(name, type) { + if (name != null) { + if (type == "var" || !HOP(this.names, name)) + this.names[name] = type || "var"; + return name; + } + }, + active_directive: function(dir) { + return member(dir, this.directives) || this.parent && this.parent.active_directive(dir); + } }; function ast_add_scope(ast) { - var current_scope = null; - var w = ast_walker(), walk = w.walk; - var having_eval = []; - - function with_new_scope(cont) { - current_scope = new Scope(current_scope); - current_scope.labels = new Scope(); - var ret = current_scope.body = cont(); - ret.scope = current_scope; - current_scope = current_scope.parent; - return ret; - }; - - function define(name, type) { - return current_scope.define(name, type); - }; - - function reference(name) { - current_scope.refs[name] = true; - }; + var current_scope = null; + var w = ast_walker(), walk = w.walk; + var having_eval = []; - function _lambda(name, args, body) { - var is_defun = this[0] == "defun"; - return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){ - if (!is_defun) define(name, "lambda"); - MAP(args, function(name){ define(name, "arg") }); - return MAP(body, walk); - })]; + function with_new_scope(cont) { + current_scope = new Scope(current_scope); + current_scope.labels = new Scope(); + var ret = current_scope.body = cont(); + ret.scope = current_scope; + current_scope = current_scope.parent; + return ret; + }; + + function define(name, type) { + return current_scope.define(name, type); + }; + + function reference(name) { + current_scope.refs[name] = true; + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun"; + return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){ + if (!is_defun) define(name, "lambda"); + MAP(args, function(name){ define(name, "arg") }); + return MAP(body, walk); + })]; + }; + + function _vardefs(type) { + return function(defs) { + MAP(defs, function(d){ + define(d[0], type); + if (d[1]) reference(d[0]); + }); }; + }; + + function _breacont(label) { + if (label) + current_scope.labels.refs[label] = true; + }; + + return with_new_scope(function(){ + // process AST + var ret = w.with_walkers({ + "function": _lambda, + "defun": _lambda, + "label": function(name, stat) { current_scope.labels.define(name) }, + "break": _breacont, + "continue": _breacont, + "with": function(expr, block) { + for (var s = current_scope; s; s = s.parent) + s.uses_with = true; + }, + "var": _vardefs("var"), + "const": _vardefs("const"), + "try": function(t, c, f) { + if (c != null) return [ + this[0], + MAP(t, walk), + [ define(c[0], "catch"), MAP(c[1], walk) ], + f != null ? MAP(f, walk) : null + ]; + }, + "name": function(name) { + if (name == "eval") + having_eval.push(current_scope); + reference(name); + } + }, function(){ + return walk(ast); + }); - function _vardefs(type) { - return function(defs) { - MAP(defs, function(d){ - define(d[0], type); - if (d[1]) reference(d[0]); - }); - }; - }; + // the reason why we need an additional pass here is + // that names can be used prior to their definition. + + // scopes where eval was detected and their parents + // are marked with uses_eval, unless they define the + // "eval" name. + MAP(having_eval, function(scope){ + if (!scope.has("eval")) while (scope) { + scope.uses_eval = true; + scope = scope.parent; + } + }); - function _breacont(label) { - if (label) - current_scope.labels.refs[label] = true; + // for referenced names it might be useful to know + // their origin scope. current_scope here is the + // toplevel one. + function fixrefs(scope, i) { + // do children first; order shouldn't matter + for (i = scope.children.length; --i >= 0;) + fixrefs(scope.children[i]); + for (i in scope.refs) if (HOP(scope.refs, i)) { + // find origin scope and propagate the reference to origin + for (var origin = scope.has(i), s = scope; s; s = s.parent) { + s.refs[i] = origin; + if (s === origin) break; + } + } }; + fixrefs(current_scope); - return with_new_scope(function(){ - // process AST - var ret = w.with_walkers({ - "function": _lambda, - "defun": _lambda, - "label": function(name, stat) { current_scope.labels.define(name) }, - "break": _breacont, - "continue": _breacont, - "with": function(expr, block) { - for (var s = current_scope; s; s = s.parent) - s.uses_with = true; - }, - "var": _vardefs("var"), - "const": _vardefs("const"), - "try": function(t, c, f) { - if (c != null) return [ - this[0], - MAP(t, walk), - [ define(c[0], "catch"), MAP(c[1], walk) ], - f != null ? MAP(f, walk) : null - ]; - }, - "name": function(name) { - if (name == "eval") - having_eval.push(current_scope); - reference(name); - } - }, function(){ - return walk(ast); - }); - - // the reason why we need an additional pass here is - // that names can be used prior to their definition. - - // scopes where eval was detected and their parents - // are marked with uses_eval, unless they define the - // "eval" name. - MAP(having_eval, function(scope){ - if (!scope.has("eval")) while (scope) { - scope.uses_eval = true; - scope = scope.parent; - } - }); - - // for referenced names it might be useful to know - // their origin scope. current_scope here is the - // toplevel one. - function fixrefs(scope, i) { - // do children first; order shouldn't matter - for (i = scope.children.length; --i >= 0;) - fixrefs(scope.children[i]); - for (i in scope.refs) if (HOP(scope.refs, i)) { - // find origin scope and propagate the reference to origin - for (var origin = scope.has(i), s = scope; s; s = s.parent) { - s.refs[i] = origin; - if (s === origin) break; - } - } - }; - fixrefs(current_scope); - - return ret; - }); + return ret; + }); }; /* -----[ mangle names ]----- */ function ast_mangle(ast, options) { - var w = ast_walker(), walk = w.walk, scope; - options = defaults(options, { - mangle : true, - toplevel : false, - defines : null, - except : null, - no_functions : false - }); - - function get_mangled(name, newMangle) { - if (!options.mangle) return name; - if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel - if (options.except && member(name, options.except)) - return name; - if (options.no_functions && HOP(scope.names, name) && - (scope.names[name] == 'defun' || scope.names[name] == 'lambda')) - return name; - return scope.get_mangled(name, newMangle); - }; - - function get_define(name) { - if (options.defines) { - // we always lookup a defined symbol for the current scope FIRST, so declared - // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value - if (!scope.has(name)) { - if (HOP(options.defines, name)) { - return options.defines[name]; - } - } - return null; - } - }; - - function _lambda(name, args, body) { - if (!options.no_functions && options.mangle) { - var is_defun = this[0] == "defun", extra; - if (name) { - if (is_defun) name = get_mangled(name); - else if (body.scope.references(name)) { - extra = {}; - if (!(scope.uses_eval || scope.uses_with)) - name = extra[name] = scope.next_mangled(); - else - extra[name] = name; - } - else name = null; - } - } - body = with_scope(body.scope, function(){ - args = MAP(args, function(name){ return get_mangled(name) }); - return MAP(body, walk); - }, extra); - return [ this[0], name, args, body ]; - }; - - function with_scope(s, cont, extra) { - var _scope = scope; - scope = s; - if (extra) for (var i in extra) if (HOP(extra, i)) { - s.set_mangle(i, extra[i]); + var w = ast_walker(), walk = w.walk, scope; + options = defaults(options, { + mangle : true, + toplevel : false, + defines : null, + except : null, + no_functions : false + }); + + function get_mangled(name, newMangle) { + if (!options.mangle) return name; + if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel + if (options.except && member(name, options.except)) + return name; + if (options.no_functions && HOP(scope.names, name) && + (scope.names[name] == 'defun' || scope.names[name] == 'lambda')) + return name; + return scope.get_mangled(name, newMangle); + }; + + function get_define(name) { + if (options.defines) { + // we always lookup a defined symbol for the current scope FIRST, so declared + // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value + if (!scope.has(name)) { + if (HOP(options.defines, name)) { + return options.defines[name]; } - for (var i in s.names) if (HOP(s.names, i)) { - get_mangled(i, true); - } - var ret = cont(); - ret.scope = s; - scope = _scope; - return ret; - }; - - function _vardefs(defs) { - return [ this[0], MAP(defs, function(d){ - return [ get_mangled(d[0]), walk(d[1]) ]; - }) ]; - }; - - function _breacont(label) { - if (label) return [ this[0], scope.labels.get_mangled(label) ]; - }; - - return w.with_walkers({ - "function": _lambda, - "defun": function() { - // move function declarations to the top when - // they are not in some block. - var ast = _lambda.apply(this, arguments); - switch (w.parent()[0]) { - case "toplevel": - case "function": - case "defun": - return MAP.at_top(ast); - } - return ast; - }, - "label": function(label, stat) { - if (scope.labels.refs[label]) return [ - this[0], - scope.labels.get_mangled(label, true), - walk(stat) - ]; - return walk(stat); - }, - "break": _breacont, - "continue": _breacont, - "var": _vardefs, - "const": _vardefs, - "name": function(name) { - return get_define(name) || [ this[0], get_mangled(name) ]; - }, - "try": function(t, c, f) { - return [ this[0], - MAP(t, walk), - c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, - f != null ? MAP(f, walk) : null ]; - }, - "toplevel": function(body) { - var self = this; - return with_scope(self.scope, function(){ - return [ self[0], MAP(body, walk) ]; - }); - }, - "directive": function() { - return MAP.at_top(this); + } + return null; + } + }; + + function _lambda(name, args, body) { + if (!options.no_functions && options.mangle) { + var is_defun = this[0] == "defun", extra; + if (name) { + if (is_defun) name = get_mangled(name); + else if (body.scope.references(name)) { + extra = {}; + if (!(scope.uses_eval || scope.uses_with)) + name = extra[name] = scope.next_mangled(); + else + extra[name] = name; } - }, function() { - return walk(ast_add_scope(ast)); - }); + else name = null; + } + } + body = with_scope(body.scope, function(){ + args = MAP(args, function(name){ return get_mangled(name) }); + return MAP(body, walk); + }, extra); + return [ this[0], name, args, body ]; + }; + + function with_scope(s, cont, extra) { + var _scope = scope; + scope = s; + if (extra) for (var i in extra) if (HOP(extra, i)) { + s.set_mangle(i, extra[i]); + } + for (var i in s.names) if (HOP(s.names, i)) { + get_mangled(i, true); + } + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + function _vardefs(defs) { + return [ this[0], MAP(defs, function(d){ + return [ get_mangled(d[0]), walk(d[1]) ]; + }) ]; + }; + + function _breacont(label) { + if (label) return [ this[0], scope.labels.get_mangled(label) ]; + }; + + return w.with_walkers({ + "function": _lambda, + "defun": function() { + // move function declarations to the top when + // they are not in some block. + var ast = _lambda.apply(this, arguments); + switch (w.parent()[0]) { + case "toplevel": + case "function": + case "defun": + return MAP.at_top(ast); + } + return ast; + }, + "label": function(label, stat) { + if (scope.labels.refs[label]) return [ + this[0], + scope.labels.get_mangled(label, true), + walk(stat) + ]; + return walk(stat); + }, + "break": _breacont, + "continue": _breacont, + "var": _vardefs, + "const": _vardefs, + "name": function(name) { + return get_define(name) || [ this[0], get_mangled(name) ]; + }, + "try": function(t, c, f) { + return [ this[0], + MAP(t, walk), + c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null ]; + }, + "toplevel": function(body) { + var self = this; + return with_scope(self.scope, function(){ + return [ self[0], MAP(body, walk) ]; + }); + }, + "directive": function() { + return MAP.at_top(this); + } + }, function() { + return walk(ast_add_scope(ast)); + }); }; /* -----[ @@ -644,1419 +644,1420 @@ function ast_mangle(ast, options) { - remove block brackets {} where possible - join consecutive var declarations - various optimizations for IFs: - - if (cond) foo(); else bar(); ==> cond?foo():bar(); - - if (cond) foo(); ==> cond&&foo(); - - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw - - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + - if (cond) foo(); else bar(); ==> cond?foo():bar(); + - if (cond) foo(); ==> cond&&foo(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} ]----- */ var warn = function(){}; function best_of(ast1, ast2) { - return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; + return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; }; function last_stat(b) { - if (b[0] == "block" && b[1] && b[1].length > 0) - return b[1][b[1].length - 1]; - return b; + if (b[0] == "block" && b[1] && b[1].length > 0) + return b[1][b[1].length - 1]; + return b; } function aborts(t) { - if (t) switch (last_stat(t)[0]) { - case "return": - case "break": - case "continue": - case "throw": - return true; - } + if (t) switch (last_stat(t)[0]) { + case "return": + case "break": + case "continue": + case "throw": + return true; + } }; function boolean_expr(expr) { - return ( (expr[0] == "unary-prefix" - && member(expr[1], [ "!", "delete" ])) || + return ( (expr[0] == "unary-prefix" + && member(expr[1], [ "!", "delete" ])) || - (expr[0] == "binary" - && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || + (expr[0] == "binary" + && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || - (expr[0] == "binary" - && member(expr[1], [ "&&", "||" ]) - && boolean_expr(expr[2]) - && boolean_expr(expr[3])) || + (expr[0] == "binary" + && member(expr[1], [ "&&", "||" ]) + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || - (expr[0] == "conditional" - && boolean_expr(expr[2]) - && boolean_expr(expr[3])) || + (expr[0] == "conditional" + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || - (expr[0] == "assign" - && expr[1] === true - && boolean_expr(expr[3])) || + (expr[0] == "assign" + && expr[1] === true + && boolean_expr(expr[3])) || - (expr[0] == "seq" - && boolean_expr(expr[expr.length - 1])) - ); + (expr[0] == "seq" + && boolean_expr(expr[expr.length - 1])) + ); }; function empty(b) { - return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); + return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); }; function is_string(node) { - return (node[0] == "string" || - node[0] == "unary-prefix" && node[1] == "typeof" || - node[0] == "binary" && node[1] == "+" && - (is_string(node[2]) || is_string(node[3]))); + return (node[0] == "string" || + node[0] == "unary-prefix" && node[1] == "typeof" || + node[0] == "binary" && node[1] == "+" && + (is_string(node[2]) || is_string(node[3]))); }; var when_constant = (function(){ - var $NOT_CONSTANT = {}; - - // this can only evaluate constant expressions. If it finds anything - // not constant, it throws $NOT_CONSTANT. - function evaluate(expr) { - switch (expr[0]) { - case "string": - case "num": - return expr[1]; - case "name": - case "atom": - switch (expr[1]) { - case "true": return true; - case "false": return false; - case "null": return null; - } - break; - case "unary-prefix": - switch (expr[1]) { - case "!": return !evaluate(expr[2]); - case "typeof": return typeof evaluate(expr[2]); - case "~": return ~evaluate(expr[2]); - case "-": return -evaluate(expr[2]); - case "+": return +evaluate(expr[2]); - } - break; - case "binary": - var left = expr[2], right = expr[3]; - switch (expr[1]) { - case "&&" : return evaluate(left) && evaluate(right); - case "||" : return evaluate(left) || evaluate(right); - case "|" : return evaluate(left) | evaluate(right); - case "&" : return evaluate(left) & evaluate(right); - case "^" : return evaluate(left) ^ evaluate(right); - case "+" : return evaluate(left) + evaluate(right); - case "*" : return evaluate(left) * evaluate(right); - case "/" : return evaluate(left) / evaluate(right); - case "%" : return evaluate(left) % evaluate(right); - case "-" : return evaluate(left) - evaluate(right); - case "<<" : return evaluate(left) << evaluate(right); - case ">>" : return evaluate(left) >> evaluate(right); - case ">>>" : return evaluate(left) >>> evaluate(right); - case "==" : return evaluate(left) == evaluate(right); - case "===" : return evaluate(left) === evaluate(right); - case "!=" : return evaluate(left) != evaluate(right); - case "!==" : return evaluate(left) !== evaluate(right); - case "<" : return evaluate(left) < evaluate(right); - case "<=" : return evaluate(left) <= evaluate(right); - case ">" : return evaluate(left) > evaluate(right); - case ">=" : return evaluate(left) >= evaluate(right); - case "in" : return evaluate(left) in evaluate(right); - case "instanceof" : return evaluate(left) instanceof evaluate(right); - } + var $NOT_CONSTANT = {}; + + // this can only evaluate constant expressions. If it finds anything + // not constant, it throws $NOT_CONSTANT. + function evaluate(expr) { + switch (expr[0]) { + case "string": + case "num": + return expr[1]; + case "name": + case "atom": + switch (expr[1]) { + case "true": return true; + case "false": return false; + case "null": return null; + } + break; + case "unary-prefix": + switch (expr[1]) { + case "!": return !evaluate(expr[2]); + case "typeof": return typeof evaluate(expr[2]); + case "~": return ~evaluate(expr[2]); + case "-": return -evaluate(expr[2]); + case "+": return +evaluate(expr[2]); + } + break; + case "binary": + var left = expr[2], right = expr[3]; + switch (expr[1]) { + case "&&" : return evaluate(left) && evaluate(right); + case "||" : return evaluate(left) || evaluate(right); + case "|" : return evaluate(left) | evaluate(right); + case "&" : return evaluate(left) & evaluate(right); + case "^" : return evaluate(left) ^ evaluate(right); + case "+" : return evaluate(left) + evaluate(right); + case "*" : return evaluate(left) * evaluate(right); + case "/" : return evaluate(left) / evaluate(right); + case "%" : return evaluate(left) % evaluate(right); + case "-" : return evaluate(left) - evaluate(right); + case "<<" : return evaluate(left) << evaluate(right); + case ">>" : return evaluate(left) >> evaluate(right); + case ">>>" : return evaluate(left) >>> evaluate(right); + case "==" : return evaluate(left) == evaluate(right); + case "===" : return evaluate(left) === evaluate(right); + case "!=" : return evaluate(left) != evaluate(right); + case "!==" : return evaluate(left) !== evaluate(right); + case "<" : return evaluate(left) < evaluate(right); + case "<=" : return evaluate(left) <= evaluate(right); + case ">" : return evaluate(left) > evaluate(right); + case ">=" : return evaluate(left) >= evaluate(right); + case "in" : return evaluate(left) in evaluate(right); + case "instanceof" : return evaluate(left) instanceof evaluate(right); + } + } + throw $NOT_CONSTANT; + }; + + return function(expr, yes, no) { + try { + var val = evaluate(expr), ast; + switch (typeof val) { + case "string": ast = [ "string", val ]; break; + case "number": ast = [ "num", val ]; break; + case "boolean": ast = [ "name", String(val) ]; break; + default: + if (val === null) { ast = [ "atom", "null" ]; break; } + throw new Error("Can't handle constant of type: " + (typeof val)); + } + return yes.call(expr, ast, val); + } catch(ex) { + if (ex === $NOT_CONSTANT) { + if (expr[0] == "binary" + && (expr[1] == "===" || expr[1] == "!==") + && ((is_string(expr[2]) && is_string(expr[3])) + || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { + expr[1] = expr[1].substr(0, 2); } - throw $NOT_CONSTANT; - }; - - return function(expr, yes, no) { - try { - var val = evaluate(expr), ast; - switch (typeof val) { - case "string": ast = [ "string", val ]; break; - case "number": ast = [ "num", val ]; break; - case "boolean": ast = [ "name", String(val) ]; break; - default: - if (val === null) { ast = [ "atom", "null" ]; break; } - throw new Error("Can't handle constant of type: " + (typeof val)); - } - return yes.call(expr, ast, val); - } catch(ex) { - if (ex === $NOT_CONSTANT) { - if (expr[0] == "binary" - && (expr[1] == "===" || expr[1] == "!==") - && ((is_string(expr[2]) && is_string(expr[3])) - || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { - expr[1] = expr[1].substr(0, 2); - } - else if (no && expr[0] == "binary" - && (expr[1] == "||" || expr[1] == "&&")) { - // the whole expression is not constant but the lval may be... - try { - var lval = evaluate(expr[2]); - expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || - (expr[1] == "||" && (lval ? lval : expr[3])) || - expr); - } catch(ex2) { - // IGNORE... lval is not constant - } - } - return no ? no.call(expr, expr) : null; - } - else throw ex; + else if (no && expr[0] == "binary" + && (expr[1] == "||" || expr[1] == "&&")) { + // the whole expression is not constant but the lval may be... + try { + var lval = evaluate(expr[2]); + expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || + (expr[1] == "||" && (lval ? lval : expr[3])) || + expr); + } catch(ex2) { + // IGNORE... lval is not constant + } } - }; + return no ? no.call(expr, expr) : null; + } + else throw ex; + } + }; })(); function warn_unreachable(ast) { - if (!empty(ast)) - warn("Dropping unreachable code: " + gen_code(ast, true)); + if (!empty(ast)) + warn("Dropping unreachable code: " + gen_code(ast, true)); }; function prepare_ifs(ast) { - var w = ast_walker(), walk = w.walk; - // In this first pass, we rewrite ifs which abort with no else with an - // if-else. For example: - // - // if (x) { - // blah(); - // return y; - // } - // foobar(); - // - // is rewritten into: - // - // if (x) { - // blah(); - // return y; - // } else { - // foobar(); - // } - function redo_if(statements) { - statements = MAP(statements, walk); - - for (var i = 0; i < statements.length; ++i) { - var fi = statements[i]; - if (fi[0] != "if") continue; - - if (fi[3]) continue; - - var t = fi[2]; - if (!aborts(t)) continue; - - var conditional = walk(fi[1]); - - var e_body = redo_if(statements.slice(i + 1)); - var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ]; - - return statements.slice(0, i).concat([ [ - fi[0], // "if" - conditional, // conditional - t, // then - e // else - ] ]); - } - - return statements; - }; - - function redo_if_lambda(name, args, body) { - body = redo_if(body); - return [ this[0], name, args, body ]; - }; - - function redo_if_block(statements) { - return [ this[0], statements != null ? redo_if(statements) : null ]; - }; + var w = ast_walker(), walk = w.walk; + // In this first pass, we rewrite ifs which abort with no else with an + // if-else. For example: + // + // if (x) { + // blah(); + // return y; + // } + // foobar(); + // + // is rewritten into: + // + // if (x) { + // blah(); + // return y; + // } else { + // foobar(); + // } + function redo_if(statements) { + statements = MAP(statements, walk); + + for (var i = 0; i < statements.length; ++i) { + var fi = statements[i]; + if (fi[0] != "if") continue; + + if (fi[3]) continue; + + var t = fi[2]; + if (!aborts(t)) continue; + + var conditional = walk(fi[1]); + + var e_body = redo_if(statements.slice(i + 1)); + var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ]; + + return statements.slice(0, i).concat([ [ + fi[0], // "if" + conditional, // conditional + t, // then + e // else + ] ]); + } - return w.with_walkers({ - "defun": redo_if_lambda, - "function": redo_if_lambda, - "block": redo_if_block, - "splice": redo_if_block, - "toplevel": function(statements) { - return [ this[0], redo_if(statements) ]; - }, - "try": function(t, c, f) { - return [ - this[0], - redo_if(t), - c != null ? [ c[0], redo_if(c[1]) ] : null, - f != null ? redo_if(f) : null - ]; - } - }, function() { - return walk(ast); - }); + return statements; + }; + + function redo_if_lambda(name, args, body) { + body = redo_if(body); + return [ this[0], name, args, body ]; + }; + + function redo_if_block(statements) { + return [ this[0], statements != null ? redo_if(statements) : null ]; + }; + + return w.with_walkers({ + "defun": redo_if_lambda, + "function": redo_if_lambda, + "block": redo_if_block, + "splice": redo_if_block, + "toplevel": function(statements) { + return [ this[0], redo_if(statements) ]; + }, + "try": function(t, c, f) { + return [ + this[0], + redo_if(t), + c != null ? [ c[0], redo_if(c[1]) ] : null, + f != null ? redo_if(f) : null + ]; + } + }, function() { + return walk(ast); + }); }; function for_side_effects(ast, handler) { - var w = ast_walker(), walk = w.walk; - var $stop = {}, $restart = {}; - function stop() { throw $stop }; - function restart() { throw $restart }; - function found(){ return handler.call(this, this, w, stop, restart) }; - function unary(op) { - if (op == "++" || op == "--") - return found.apply(this, arguments); - }; - function binary(op) { - if (op == "&&" || op == "||") - return found.apply(this, arguments); - }; - return w.with_walkers({ - "try": found, - "throw": found, - "return": found, - "new": found, - "switch": found, - "break": found, - "continue": found, - "assign": found, - "call": found, - "if": found, - "for": found, - "for-in": found, - "while": found, - "do": found, - "return": found, - "unary-prefix": unary, - "unary-postfix": unary, - "conditional": found, - "binary": binary, - "defun": found - }, function(){ - while (true) try { - walk(ast); - break; - } catch(ex) { - if (ex === $stop) break; - if (ex === $restart) continue; - throw ex; - } - }); + var w = ast_walker(), walk = w.walk; + var $stop = {}, $restart = {}; + function stop() { throw $stop }; + function restart() { throw $restart }; + function found(){ return handler.call(this, this, w, stop, restart) }; + function unary(op) { + if (op == "++" || op == "--") + return found.apply(this, arguments); + }; + function binary(op) { + if (op == "&&" || op == "||") + return found.apply(this, arguments); + }; + return w.with_walkers({ + "try": found, + "throw": found, + "return": found, + "new": found, + "switch": found, + "break": found, + "continue": found, + "assign": found, + "call": found, + "if": found, + "for": found, + "for-in": found, + "while": found, + "do": found, + "return": found, + "unary-prefix": unary, + "unary-postfix": unary, + "conditional": found, + "binary": binary, + "defun": found + }, function(){ + while (true) try { + walk(ast); + break; + } catch(ex) { + if (ex === $stop) break; + if (ex === $restart) continue; + throw ex; + } + }); }; function ast_lift_variables(ast) { - var w = ast_walker(), walk = w.walk, scope; - function do_body(body, env) { - var _scope = scope; - scope = env; - body = MAP(body, walk); - var hash = {}, names = MAP(env.names, function(type, name){ - if (type != "var") return MAP.skip; - if (!env.references(name)) return MAP.skip; - hash[name] = true; - return [ name ]; - }); - if (names.length > 0) { - // looking for assignments to any of these variables. - // we can save considerable space by moving the definitions - // in the var declaration. - for_side_effects([ "block", body ], function(ast, walker, stop, restart) { - if (ast[0] == "assign" - && ast[1] === true - && ast[2][0] == "name" - && HOP(hash, ast[2][1])) { - // insert the definition into the var declaration - for (var i = names.length; --i >= 0;) { - if (names[i][0] == ast[2][1]) { - if (names[i][1]) // this name already defined, we must stop - stop(); - names[i][1] = ast[3]; // definition - names.push(names.splice(i, 1)[0]); - break; - } - } - // remove this assignment from the AST. - var p = walker.parent(); - if (p[0] == "seq") { - var a = p[2]; - a.unshift(0, p.length); - p.splice.apply(p, a); - } - else if (p[0] == "stat") { - p.splice(0, p.length, "block"); // empty statement - } - else { - stop(); - } - restart(); - } + var w = ast_walker(), walk = w.walk, scope; + function do_body(body, env) { + var _scope = scope; + scope = env; + body = MAP(body, walk); + var hash = {}, names = MAP(env.names, function(type, name){ + if (type != "var") return MAP.skip; + if (!env.references(name)) return MAP.skip; + hash[name] = true; + return [ name ]; + }); + if (names.length > 0) { + // looking for assignments to any of these variables. + // we can save considerable space by moving the definitions + // in the var declaration. + for_side_effects([ "block", body ], function(ast, walker, stop, restart) { + if (ast[0] == "assign" + && ast[1] === true + && ast[2][0] == "name" + && HOP(hash, ast[2][1])) { + // insert the definition into the var declaration + for (var i = names.length; --i >= 0;) { + if (names[i][0] == ast[2][1]) { + if (names[i][1]) // this name already defined, we must stop stop(); - }); - body.unshift([ "var", names ]); - } - scope = _scope; - return body; - }; - function _vardefs(defs) { - var ret = null; - for (var i = defs.length; --i >= 0;) { - var d = defs[i]; - if (!d[1]) continue; - d = [ "assign", true, [ "name", d[0] ], d[1] ]; - if (ret == null) ret = d; - else ret = [ "seq", d, ret ]; - } - if (ret == null && w.parent()[0] != "for") { - if (w.parent()[0] == "for-in") - return [ "name", defs[0][0] ]; - return MAP.skip; + names[i][1] = ast[3]; // definition + names.push(names.splice(i, 1)[0]); + break; + } + } + // remove this assignment from the AST. + var p = walker.parent(); + if (p[0] == "seq") { + var a = p[2]; + a.unshift(0, p.length); + p.splice.apply(p, a); + } + else if (p[0] == "stat") { + p.splice(0, p.length, "block"); // empty statement + } + else { + stop(); + } + restart(); } - return [ "stat", ret ]; - }; - function _toplevel(body) { - return [ this[0], do_body(body, this.scope) ]; - }; - return w.with_walkers({ - "function": function(name, args, body){ - for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) - args.pop(); - if (!body.scope.references(name)) name = null; - return [ this[0], name, args, do_body(body, body.scope) ]; - }, - "defun": function(name, args, body){ - if (!scope.references(name)) return MAP.skip; - for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) - args.pop(); - return [ this[0], name, args, do_body(body, body.scope) ]; - }, - "var": _vardefs, - "toplevel": _toplevel - }, function(){ - return walk(ast_add_scope(ast)); - }); + stop(); + }); + body.unshift([ "var", names ]); + } + scope = _scope; + return body; + }; + function _vardefs(defs) { + var ret = null; + for (var i = defs.length; --i >= 0;) { + var d = defs[i]; + if (!d[1]) continue; + d = [ "assign", true, [ "name", d[0] ], d[1] ]; + if (ret == null) ret = d; + else ret = [ "seq", d, ret ]; + } + if (ret == null && w.parent()[0] != "for") { + if (w.parent()[0] == "for-in") + return [ "name", defs[0][0] ]; + return MAP.skip; + } + return [ "stat", ret ]; + }; + function _toplevel(body) { + return [ this[0], do_body(body, this.scope) ]; + }; + return w.with_walkers({ + "function": function(name, args, body){ + for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) + args.pop(); + if (!body.scope.references(name)) name = null; + return [ this[0], name, args, do_body(body, body.scope) ]; + }, + "defun": function(name, args, body){ + if (!scope.references(name)) return MAP.skip; + for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) + args.pop(); + return [ this[0], name, args, do_body(body, body.scope) ]; + }, + "var": _vardefs, + "toplevel": _toplevel + }, function(){ + return walk(ast_add_scope(ast)); + }); }; function ast_squeeze(ast, options) { - ast = squeeze_1(ast, options); - ast = squeeze_2(ast, options); - return ast; + ast = squeeze_1(ast, options); + ast = squeeze_2(ast, options); + return ast; }; function squeeze_1(ast, options) { - options = defaults(options, { - make_seqs : true, - dead_code : true, - no_warnings : false, - keep_comps : true, - unsafe : false - }); - - var w = ast_walker(), walk = w.walk, scope; - - function negate(c) { - var not_c = [ "unary-prefix", "!", c ]; - switch (c[0]) { - case "unary-prefix": - return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; - case "seq": - c = slice(c); - c[c.length - 1] = negate(c[c.length - 1]); - return c; - case "conditional": - return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); - case "binary": - var op = c[1], left = c[2], right = c[3]; - if (!options.keep_comps) switch (op) { - case "<=" : return [ "binary", ">", left, right ]; - case "<" : return [ "binary", ">=", left, right ]; - case ">=" : return [ "binary", "<", left, right ]; - case ">" : return [ "binary", "<=", left, right ]; - } - switch (op) { - case "==" : return [ "binary", "!=", left, right ]; - case "!=" : return [ "binary", "==", left, right ]; - case "===" : return [ "binary", "!==", left, right ]; - case "!==" : return [ "binary", "===", left, right ]; - case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); - case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); - } - break; - } - return not_c; - }; - - function make_conditional(c, t, e) { - var make_real_conditional = function() { - if (c[0] == "unary-prefix" && c[1] == "!") { - return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; - } else { - return e ? best_of( - [ "conditional", c, t, e ], - [ "conditional", negate(c), e, t ] - ) : [ "binary", "&&", c, t ]; - } - }; - // shortcut the conditional if the expression has a constant value - return when_constant(c, function(ast, val){ - warn_unreachable(val ? e : t); - return (val ? t : e); - }, make_real_conditional); - }; - - function rmblock(block) { - if (block != null && block[0] == "block" && block[1]) { - if (block[1].length == 1) - block = block[1][0]; - else if (block[1].length == 0) - block = [ "block" ]; - } - return block; - }; - - function _lambda(name, args, body) { - return [ this[0], name, args, tighten(body, "lambda") ]; - }; - - // this function does a few things: - // 1. discard useless blocks - // 2. join consecutive var declarations - // 3. remove obviously dead code - // 4. transform consecutive statements using the comma operator - // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } - function tighten(statements, block_type) { - statements = MAP(statements, walk); - - statements = statements.reduce(function(a, stat){ - if (stat[0] == "block") { - if (stat[1]) { - a.push.apply(a, stat[1]); - } - } else { - a.push(stat); - } - return a; - }, []); - - statements = (function(a, prev){ - statements.forEach(function(cur){ - if (prev && ((cur[0] == "var" && prev[0] == "var") || - (cur[0] == "const" && prev[0] == "const"))) { - prev[1] = prev[1].concat(cur[1]); - } else { - a.push(cur); - prev = cur; - } - }); - return a; - })([]); - - if (options.dead_code) statements = (function(a, has_quit){ - statements.forEach(function(st){ - if (has_quit) { - if (st[0] == "function" || st[0] == "defun") { - a.push(st); - } - else if (st[0] == "var" || st[0] == "const") { - if (!options.no_warnings) - warn("Variables declared in unreachable code"); - st[1] = MAP(st[1], function(def){ - if (def[1] && !options.no_warnings) - warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]); - return [ def[0] ]; - }); - a.push(st); - } - else if (!options.no_warnings) - warn_unreachable(st); - } - else { - a.push(st); - if (member(st[0], [ "return", "throw", "break", "continue" ])) - has_quit = true; - } - }); - return a; - })([]); - - if (options.make_seqs) statements = (function(a, prev) { - statements.forEach(function(cur){ - if (prev && prev[0] == "stat" && cur[0] == "stat") { - prev[1] = [ "seq", prev[1], cur[1] ]; - } else { - a.push(cur); - prev = cur; - } - }); - if (a.length >= 2 - && a[a.length-2][0] == "stat" - && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw") - && a[a.length-1][1]) - { - a.splice(a.length - 2, 2, - [ a[a.length-1][0], - [ "seq", a[a.length-2][1], a[a.length-1][1] ]]); - } - return a; - })([]); - - // this increases jQuery by 1K. Probably not such a good idea after all.. - // part of this is done in prepare_ifs anyway. - // if (block_type == "lambda") statements = (function(i, a, stat){ - // while (i < statements.length) { - // stat = statements[i++]; - // if (stat[0] == "if" && !stat[3]) { - // if (stat[2][0] == "return" && stat[2][1] == null) { - // a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); - // break; - // } - // var last = last_stat(stat[2]); - // if (last[0] == "return" && last[1] == null) { - // a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); - // break; - // } - // } - // a.push(stat); - // } - // return a; - // })(0, []); - - return statements; - }; - - function make_if(c, t, e) { - return when_constant(c, function(ast, val){ - if (val) { - t = walk(t); - warn_unreachable(e); - return t || [ "block" ]; - } else { - e = walk(e); - warn_unreachable(t); - return e || [ "block" ]; - } - }, function() { - return make_real_if(c, t, e); - }); + options = defaults(options, { + make_seqs : true, + dead_code : true, + no_warnings : false, + keep_comps : true, + unsafe : false + }); + + var w = ast_walker(), walk = w.walk, scope; + + function negate(c) { + var not_c = [ "unary-prefix", "!", c ]; + switch (c[0]) { + case "unary-prefix": + return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; + case "seq": + c = slice(c); + c[c.length - 1] = negate(c[c.length - 1]); + return c; + case "conditional": + return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); + case "binary": + var op = c[1], left = c[2], right = c[3]; + if (!options.keep_comps) switch (op) { + case "<=" : return [ "binary", ">", left, right ]; + case "<" : return [ "binary", ">=", left, right ]; + case ">=" : return [ "binary", "<", left, right ]; + case ">" : return [ "binary", "<=", left, right ]; + } + switch (op) { + case "==" : return [ "binary", "!=", left, right ]; + case "!=" : return [ "binary", "==", left, right ]; + case "===" : return [ "binary", "!==", left, right ]; + case "!==" : return [ "binary", "===", left, right ]; + case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); + case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); + } + break; + } + return not_c; + }; + + function make_conditional(c, t, e) { + var make_real_conditional = function() { + if (c[0] == "unary-prefix" && c[1] == "!") { + return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; + } else { + return e ? best_of( + [ "conditional", c, t, e ], + [ "conditional", negate(c), e, t ] + ) : [ "binary", "&&", c, t ]; + } }; - - function abort_else(c, t, e) { - var ret = [ [ "if", negate(c), e ] ]; - if (t[0] == "block") { - if (t[1]) ret = ret.concat(t[1]); - } else { - ret.push(t); + // shortcut the conditional if the expression has a constant value + return when_constant(c, function(ast, val){ + warn_unreachable(val ? e : t); + return (val ? t : e); + }, make_real_conditional); + }; + + function rmblock(block) { + if (block != null && block[0] == "block" && block[1]) { + if (block[1].length == 1) + block = block[1][0]; + else if (block[1].length == 0) + block = [ "block" ]; + } + return block; + }; + + function _lambda(name, args, body) { + return [ this[0], name, args, tighten(body, "lambda") ]; + }; + + // this function does a few things: + // 1. discard useless blocks + // 2. join consecutive var declarations + // 3. remove obviously dead code + // 4. transform consecutive statements using the comma operator + // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } + function tighten(statements, block_type) { + statements = MAP(statements, walk); + + statements = statements.reduce(function(a, stat){ + if (stat[0] == "block") { + if (stat[1]) { + a.push.apply(a, stat[1]); } - return walk([ "block", ret ]); - }; - - function make_real_if(c, t, e) { - c = walk(c); - t = walk(t); - e = walk(e); - - if (empty(e) && empty(t)) - return [ "stat", c ]; - - if (empty(t)) { - c = negate(c); - t = e; - e = null; - } else if (empty(e)) { - e = null; + } else { + a.push(stat); + } + return a; + }, []); + + statements = (function(a, prev){ + statements.forEach(function(cur){ + if (prev && ((cur[0] == "var" && prev[0] == "var") || + (cur[0] == "const" && prev[0] == "const"))) { + prev[1] = prev[1].concat(cur[1]); } else { - // if we have both else and then, maybe it makes sense to switch them? - (function(){ - var a = gen_code(c); - var n = negate(c); - var b = gen_code(n); - if (b.length < a.length) { - var tmp = t; - t = e; - e = tmp; - c = n; - } - })(); + a.push(cur); + prev = cur; } - var ret = [ "if", c, t, e ]; - if (t[0] == "if" && empty(t[3]) && empty(e)) { - ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); - } - else if (t[0] == "stat") { - if (e) { - if (e[0] == "stat") - ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); - else if (aborts(e)) - ret = abort_else(c, t, e); - } - else { - ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); - } - } - else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { - ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); + }); + return a; + })([]); + + if (options.dead_code) statements = (function(a, has_quit){ + statements.forEach(function(st){ + if (has_quit) { + if (st[0] == "function" || st[0] == "defun") { + a.push(st); + } + else if (st[0] == "var" || st[0] == "const") { + if (!options.no_warnings) + warn("Variables declared in unreachable code"); + st[1] = MAP(st[1], function(def){ + if (def[1] && !options.no_warnings) + warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]); + return [ def[0] ]; + }); + a.push(st); + } + else if (!options.no_warnings) + warn_unreachable(st); } - else if (e && aborts(t)) { - ret = [ [ "if", c, t ] ]; - if (e[0] == "block") { - if (e[1]) ret = ret.concat(e[1]); - } - else { - ret.push(e); - } - ret = walk([ "block", ret ]); + else { + a.push(st); + if (member(st[0], [ "return", "throw", "break", "continue" ])) + has_quit = true; } - else if (t && aborts(e)) { - ret = abort_else(c, t, e); + }); + return a; + })([]); + + if (options.make_seqs) statements = (function(a, prev) { + statements.forEach(function(cur){ + if (prev && prev[0] == "stat" && cur[0] == "stat") { + prev[1] = [ "seq", prev[1], cur[1] ]; + } else { + a.push(cur); + prev = cur; } - return ret; - }; - - function _do_while(cond, body) { - return when_constant(cond, function(cond, val){ - if (!val) { - warn_unreachable(body); - return [ "block" ]; - } else { - return [ "for", null, null, null, walk(body) ]; - } - }); - }; + }); + if (a.length >= 2 + && a[a.length-2][0] == "stat" + && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw") + && a[a.length-1][1]) + { + a.splice(a.length - 2, 2, + [ a[a.length-1][0], + [ "seq", a[a.length-2][1], a[a.length-1][1] ]]); + } + return a; + })([]); + + // this increases jQuery by 1K. Probably not such a good idea after all.. + // part of this is done in prepare_ifs anyway. + // if (block_type == "lambda") statements = (function(i, a, stat){ + // while (i < statements.length) { + // stat = statements[i++]; + // if (stat[0] == "if" && !stat[3]) { + // if (stat[2][0] == "return" && stat[2][1] == null) { + // a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); + // break; + // } + // var last = last_stat(stat[2]); + // if (last[0] == "return" && last[1] == null) { + // a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); + // break; + // } + // } + // a.push(stat); + // } + // return a; + // })(0, []); + + return statements; + }; + + function make_if(c, t, e) { + return when_constant(c, function(ast, val){ + if (val) { + t = walk(t); + warn_unreachable(e); + return t || [ "block" ]; + } else { + e = walk(e); + warn_unreachable(t); + return e || [ "block" ]; + } + }, function() { + return make_real_if(c, t, e); + }); + }; - return w.with_walkers({ - "sub": function(expr, subscript) { - if (subscript[0] == "string") { - var name = subscript[1]; - if (is_identifier(name)) - return [ "dot", walk(expr), name ]; - else if (/^[1-9][0-9]*$/.test(name) || name === "0") - return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; - } - }, - "if": make_if, - "toplevel": function(body) { - return [ "toplevel", tighten(body) ]; - }, - "switch": function(expr, body) { - var last = body.length - 1; - return [ "switch", walk(expr), MAP(body, function(branch, i){ - var block = tighten(branch[1]); - if (i == last && block.length > 0) { - var node = block[block.length - 1]; - if (node[0] == "break" && !node[1]) - block.pop(); - } - return [ branch[0] ? walk(branch[0]) : null, block ]; - }) ]; - }, - "function": _lambda, - "defun": _lambda, - "block": function(body) { - if (body) return rmblock([ "block", tighten(body) ]); - }, - "binary": function(op, left, right) { - return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ - return best_of(walk(c), this); - }, function no() { - return function(){ - if(op != "==" && op != "!=") return; - var l = walk(left), r = walk(right); - if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num") - left = ['num', +!l[2][1]]; - else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num") - right = ['num', +!r[2][1]]; - return ["binary", op, left, right]; - }() || this; - }); - }, - "conditional": function(c, t, e) { - return make_conditional(walk(c), walk(t), walk(e)); - }, - "try": function(t, c, f) { - return [ - "try", - tighten(t), - c != null ? [ c[0], tighten(c[1]) ] : null, - f != null ? tighten(f) : null - ]; - }, - "unary-prefix": function(op, expr) { - expr = walk(expr); - var ret = [ "unary-prefix", op, expr ]; - if (op == "!") - ret = best_of(ret, negate(expr)); - return when_constant(ret, function(ast, val){ - return walk(ast); // it's either true or false, so minifies to !0 or !1 - }, function() { return ret }); - }, - "name": function(name) { - switch (name) { - case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; - case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; - } - }, - "while": _do_while, - "assign": function(op, lvalue, rvalue) { - lvalue = walk(lvalue); - rvalue = walk(rvalue); - var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; - if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" && - ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" && - rvalue[2][1] === lvalue[1]) { - return [ this[0], rvalue[1], lvalue, rvalue[3] ] - } - return [ this[0], op, lvalue, rvalue ]; - }, - "call": function(expr, args) { - expr = walk(expr); - if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") { - return expr[1]; - } - return [ this[0], expr, MAP(args, walk) ]; - }, - "num": function (num) { - if (!isFinite(num)) - return [ "binary", "/", num === 1 / 0 - ? [ "num", 1 ] : num === -1 / 0 - ? [ "unary-prefix", "-", [ "num", 1 ] ] - : [ "num", 0 ], [ "num", 0 ] ]; - - return [ this[0], num ]; + function abort_else(c, t, e) { + var ret = [ [ "if", negate(c), e ] ]; + if (t[0] == "block") { + if (t[1]) ret = ret.concat(t[1]); + } else { + ret.push(t); + } + return walk([ "block", ret ]); + }; + + function make_real_if(c, t, e) { + c = walk(c); + t = walk(t); + e = walk(e); + + if (empty(e) && empty(t)) + return [ "stat", c ]; + + if (empty(t)) { + c = negate(c); + t = e; + e = null; + } else if (empty(e)) { + e = null; + } else { + // if we have both else and then, maybe it makes sense to switch them? + (function(){ + var a = gen_code(c); + var n = negate(c); + var b = gen_code(n); + if (b.length < a.length) { + var tmp = t; + t = e; + e = tmp; + c = n; } - }, function() { - return walk(prepare_ifs(walk(prepare_ifs(ast)))); + })(); + } + var ret = [ "if", c, t, e ]; + if (t[0] == "if" && empty(t[3]) && empty(e)) { + ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); + } + else if (t[0] == "stat") { + if (e) { + if (e[0] == "stat") + ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); + else if (aborts(e)) + ret = abort_else(c, t, e); + } + else { + ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); + } + } + else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { + ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); + } + else if (e && aborts(t)) { + ret = [ [ "if", c, t ] ]; + if (e[0] == "block") { + if (e[1]) ret = ret.concat(e[1]); + } + else { + ret.push(e); + } + ret = walk([ "block", ret ]); + } + else if (t && aborts(e)) { + ret = abort_else(c, t, e); + } + return ret; + }; + + function _do_while(cond, body) { + return when_constant(cond, function(cond, val){ + if (!val) { + warn_unreachable(body); + return [ "block" ]; + } else { + return [ "for", null, null, null, walk(body) ]; + } }); + }; + + return w.with_walkers({ + "sub": function(expr, subscript) { + if (subscript[0] == "string") { + var name = subscript[1]; + if (is_identifier(name)) + return [ "dot", walk(expr), name ]; + else if (/^[1-9][0-9]*$/.test(name) || name === "0") + return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; + } + }, + "if": make_if, + "toplevel": function(body) { + return [ "toplevel", tighten(body) ]; + }, + "switch": function(expr, body) { + var last = body.length - 1; + return [ "switch", walk(expr), MAP(body, function(branch, i){ + var block = tighten(branch[1]); + if (i == last && block.length > 0) { + var node = block[block.length - 1]; + if (node[0] == "break" && !node[1]) + block.pop(); + } + return [ branch[0] ? walk(branch[0]) : null, block ]; + }) ]; + }, + "function": _lambda, + "defun": _lambda, + "block": function(body) { + if (body) return rmblock([ "block", tighten(body) ]); + }, + "binary": function(op, left, right) { + return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ + return best_of(walk(c), this); + }, function no() { + return function(){ + if(op != "==" && op != "!=") return; + var l = walk(left), r = walk(right); + if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num") + left = ['num', +!l[2][1]]; + else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num") + right = ['num', +!r[2][1]]; + return ["binary", op, left, right]; + }() || this; + }); + }, + "conditional": function(c, t, e) { + return make_conditional(walk(c), walk(t), walk(e)); + }, + "try": function(t, c, f) { + return [ + "try", + tighten(t), + c != null ? [ c[0], tighten(c[1]) ] : null, + f != null ? tighten(f) : null + ]; + }, + "unary-prefix": function(op, expr) { + expr = walk(expr); + var ret = [ "unary-prefix", op, expr ]; + if (op == "!") + ret = best_of(ret, negate(expr)); + return when_constant(ret, function(ast, val){ + return walk(ast); // it's either true or false, so minifies to !0 or !1 + }, function() { return ret }); + }, + "name": function(name) { + switch (name) { + case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; + case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; + } + }, + "while": _do_while, + "assign": function(op, lvalue, rvalue) { + lvalue = walk(lvalue); + rvalue = walk(rvalue); + var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" && + ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" && + rvalue[2][1] === lvalue[1]) { + return [ this[0], rvalue[1], lvalue, rvalue[3] ] + } + return [ this[0], op, lvalue, rvalue ]; + }, + "call": function(expr, args) { + expr = walk(expr); + if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") { + return expr[1]; + } + return [ this[0], expr, MAP(args, walk) ]; + }, + "num": function (num) { + if (!isFinite(num)) + return [ "binary", "/", num === 1 / 0 + ? [ "num", 1 ] : num === -1 / 0 + ? [ "unary-prefix", "-", [ "num", 1 ] ] + : [ "num", 0 ], [ "num", 0 ] ]; + + return [ this[0], num ]; + } + }, function() { + return walk(prepare_ifs(walk(prepare_ifs(ast)))); + }); }; function squeeze_2(ast, options) { - var w = ast_walker(), walk = w.walk, scope; - function with_scope(s, cont) { - var save = scope, ret; - scope = s; - ret = cont(); - scope = save; - return ret; - }; - function lambda(name, args, body) { - return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; - }; - return w.with_walkers({ - "directive": function(dir) { - if (scope.active_directive(dir)) - return [ "block" ]; - scope.directives.push(dir); - }, - "toplevel": function(body) { - return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; - }, - "function": lambda, - "defun": lambda - }, function(){ - return walk(ast_add_scope(ast)); - }); + var w = ast_walker(), walk = w.walk, scope; + function with_scope(s, cont) { + var save = scope, ret; + scope = s; + ret = cont(); + scope = save; + return ret; + }; + function lambda(name, args, body) { + return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; + }; + return w.with_walkers({ + "directive": function(dir) { + if (scope.active_directive(dir)) + return [ "block" ]; + scope.directives.push(dir); + }, + "toplevel": function(body) { + return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; + }, + "function": lambda, + "defun": lambda + }, function(){ + return walk(ast_add_scope(ast)); + }); }; /* -----[ re-generate code from the AST ]----- */ var DOT_CALL_NO_PARENS = jsp.array_to_hash([ - "name", - "array", - "object", - "string", - "dot", - "sub", - "call", - "regexp", - "defun" + "name", + "array", + "object", + "string", + "dot", + "sub", + "call", + "regexp", + "defun" ]); function make_string(str, ascii_only) { - var dq = 0, sq = 0; - str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ - switch (s) { - case "\\": return "\\\\"; - case "\b": return "\\b"; - case "\f": return "\\f"; - case "\n": return "\\n"; - case "\r": return "\\r"; - case "\u2028": return "\\u2028"; - case "\u2029": return "\\u2029"; - case '"': ++dq; return '"'; - case "'": ++sq; return "'"; - case "\0": return "\\0"; - } - return s; - }); - if (ascii_only) str = to_ascii(str); - if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; - else return '"' + str.replace(/\x22/g, '\\"') + '"'; + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; }; function to_ascii(str) { - return str.replace(/[\u0080-\uffff]/g, function(ch) { - var code = ch.charCodeAt(0).toString(16); - while (code.length < 4) code = "0" + code; - return "\\u" + code; - }); + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + while (code.length < 4) code = "0" + code; + return "\\u" + code; + }); }; var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]); function gen_code(ast, options) { - options = defaults(options, { - indent_start : 0, - indent_level : 4, - quote_keys : false, - space_colon : false, - beautify : false, - ascii_only : false, - inline_script: false - }); - var beautify = !!options.beautify; - var indentation = 0, - newline = beautify ? "\n" : "", - space = beautify ? " " : ""; - - function encode_string(str) { - var ret = make_string(str, options.ascii_only); - if (options.inline_script) - ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); - return ret; - }; - - function make_name(name) { - name = name.toString(); - if (options.ascii_only) - name = to_ascii(name); - return name; - }; - - function indent(line) { - if (line == null) - line = ""; - if (beautify) - line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; - return line; - }; - - function with_indent(cont, incr) { - if (incr == null) incr = 1; - indentation += incr; - try { return cont.apply(null, slice(arguments, 1)); } - finally { indentation -= incr; } - }; - - function last_char(str) { - str = str.toString(); - return str.charAt(str.length - 1); - }; - - function first_char(str) { - return str.toString().charAt(0); - }; - - function add_spaces(a) { - if (beautify) - return a.join(" "); - var b = []; - for (var i = 0; i < a.length; ++i) { - var next = a[i + 1]; - b.push(a[i]); - if (next && - ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next)) - || first_char(next) == "\\")) || - (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) { - b.push(" "); - } - } - return b.join(""); - }; - - function add_commas(a) { - return a.join("," + space); - }; - - function parenthesize(expr) { - var gen = make(expr); - for (var i = 1; i < arguments.length; ++i) { - var el = arguments[i]; - if ((el instanceof Function && el(expr)) || expr[0] == el) - return "(" + gen + ")"; - } - return gen; - }; + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : false, + beautify : false, + ascii_only : false, + inline_script: false + }); + var beautify = !!options.beautify; + var indentation = 0, + newline = beautify ? "\n" : "", + space = beautify ? " " : ""; + + function encode_string(str) { + var ret = make_string(str, options.ascii_only); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name); + return name; + }; + + function indent(line) { + if (line == null) + line = ""; + if (beautify) + line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; + return line; + }; + + function with_indent(cont, incr) { + if (incr == null) incr = 1; + indentation += incr; + try { return cont.apply(null, slice(arguments, 1)); } + finally { indentation -= incr; } + }; + + function last_char(str) { + str = str.toString(); + return str.charAt(str.length - 1); + }; + + function first_char(str) { + return str.toString().charAt(0); + }; + + function add_spaces(a) { + if (beautify) + return a.join(" "); + var b = []; + for (var i = 0; i < a.length; ++i) { + var next = a[i + 1]; + b.push(a[i]); + if (next && + ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next)) + || first_char(next) == "\\")) || + (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString()) || + last_char(a[i]) == "/" && first_char(next) == "/"))) { + b.push(" "); + } + } + return b.join(""); + }; + + function add_commas(a) { + return a.join("," + space); + }; + + function parenthesize(expr) { + var gen = make(expr); + for (var i = 1; i < arguments.length; ++i) { + var el = arguments[i]; + if ((el instanceof Function && el(expr)) || expr[0] == el) + return "(" + gen + ")"; + } + return gen; + }; - function best_of(a) { - if (a.length == 1) { - return a[0]; + function best_of(a) { + if (a.length == 1) { + return a[0]; + } + if (a.length == 2) { + var b = a[1]; + a = a[0]; + return a.length <= b.length ? a : b; + } + return best_of([ a[0], best_of(a.slice(1)) ]); + }; + + function needs_parens(expr) { + if (expr[0] == "function" || expr[0] == "object") { + // dot/call on a literal function requires the + // function literal itself to be parenthesized + // only if it's the first "thing" in a + // statement. This means that the parent is + // "stat", but it could also be a "seq" and + // we're the first in this "seq" and the + // parent is "stat", and so on. Messy stuff, + // but it worths the trouble. + var a = slice(w.stack()), self = a.pop(), p = a.pop(); + while (p) { + if (p[0] == "stat") return true; + if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || + ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { + self = p; + p = a.pop(); + } else { + return false; } - if (a.length == 2) { - var b = a[1]; - a = a[0]; - return a.length <= b.length ? a : b; + } + } + return !HOP(DOT_CALL_NO_PARENS, expr[0]); + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + var w = ast_walker(); + var make = w.walk; + return w.with_walkers({ + "string": encode_string, + "num": make_num, + "name": make_name, + "debugger": function(){ return "debugger;" }, + "toplevel": function(statements) { + return make_block_statements(statements) + .join(newline + newline); + }, + "splice": function(statements) { + var parent = w.parent(); + if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { + // we need block brackets in this case + return make_block.apply(this, arguments); + } else { + return MAP(make_block_statements(statements, true), + function(line, i) { + // the first line is already indented + return i > 0 ? indent(line) : line; + }).join(newline); + } + }, + "block": make_block, + "var": function(defs) { + return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "const": function(defs) { + return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "try": function(tr, ca, fi) { + var out = [ "try", make_block(tr) ]; + if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); + if (fi) out.push("finally", make_block(fi)); + return add_spaces(out); + }, + "throw": function(expr) { + return add_spaces([ "throw", make(expr) ]) + ";"; + }, + "new": function(ctor, args) { + args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){ + return parenthesize(expr, "seq"); + })) + ")" : ""; + return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ + var w = ast_walker(), has_call = {}; + try { + w.with_walkers({ + "call": function() { throw has_call }, + "function": function() { return this } + }, function(){ + w.walk(expr); + }); + } catch(ex) { + if (ex === has_call) + return true; + throw ex; } - return best_of([ a[0], best_of(a.slice(1)) ]); - }; + }) + args ]); + }, + "switch": function(expr, body) { + return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); + }, + "break": function(label) { + var out = "break"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "continue": function(label) { + var out = "continue"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "conditional": function(co, th, el) { + return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", + parenthesize(th, "seq"), ":", + parenthesize(el, "seq") ]); + }, + "assign": function(op, lvalue, rvalue) { + if (op && op !== true) op += "="; + else op = "="; + return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); + }, + "dot": function(expr) { + var out = make(expr), i = 1; + if (expr[0] == "num") { + if (!/[a-f.]/i.test(out)) + out += "."; + } else if (expr[0] != "function" && needs_parens(expr)) + out = "(" + out + ")"; + while (i < arguments.length) + out += "." + make_name(arguments[i++]); + return out; + }, + "call": function(func, args) { + var f = make(func); + if (f.charAt(0) != "(" && needs_parens(func)) + f = "(" + f + ")"; + return f + "(" + add_commas(MAP(args, function(expr){ + return parenthesize(expr, "seq"); + })) + ")"; + }, + "function": make_function, + "defun": make_function, + "if": function(co, th, el) { + var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; + if (el) { + out.push("else", make(el)); + } + return add_spaces(out); + }, + "for": function(init, cond, step, block) { + var out = [ "for" ]; + init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); + cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); + step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); + var args = init + cond + step; + if (args == "; ; ") args = ";;"; + out.push("(" + args + ")", make(block)); + return add_spaces(out); + }, + "for-in": function(vvar, key, hash, block) { + return add_spaces([ "for", "(" + + (vvar ? make(vvar).replace(/;+$/, "") : make(key)), + "in", + make(hash) + ")", make(block) ]); + }, + "while": function(condition, block) { + return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); + }, + "do": function(condition, block) { + return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; + }, + "return": function(expr) { + var out = [ "return" ]; + if (expr != null) out.push(make(expr)); + return add_spaces(out) + ";"; + }, + "binary": function(operator, lvalue, rvalue) { + var left = make(lvalue), right = make(rvalue); + // XXX: I'm pretty sure other cases will bite here. + // we need to be smarter. + // adding parens all the time is the safest bet. + if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || + lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] || + lvalue[0] == "function" && needs_parens(this)) { + left = "(" + left + ")"; + } + if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || + rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && + !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { + right = "(" + right + ")"; + } + else if (!beautify && options.inline_script && (operator == "<" || operator == "<<") + && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { + right = " " + right; + } + return add_spaces([ left, operator, right ]); + }, + "unary-prefix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; + }, + "unary-postfix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return val + operator; + }, + "sub": function(expr, subscript) { + var hash = make(expr); + if (needs_parens(expr)) + hash = "(" + hash + ")"; + return hash + "[" + make(subscript) + "]"; + }, + "object": function(props) { + var obj_needs_parens = needs_parens(this); + if (props.length == 0) + return obj_needs_parens ? "({})" : "{}"; + var out = "{" + newline + with_indent(function(){ + return MAP(props, function(p){ + if (p.length == 3) { + // getter/setter. The name is in p[0], the arg.list in p[1][2], the + // body in p[1][3] and type ("get" / "set") in p[2]. + return indent(make_function(p[0], p[1][2], p[1][3], p[2], true)); + } + var key = p[0], val = parenthesize(p[1], "seq"); + if (options.quote_keys) { + key = encode_string(key); + } else if ((typeof key == "number" || !beautify && +key + "" == key) + && parseFloat(key) >= 0) { + key = make_num(+key); + } else if (!is_identifier(key)) { + key = encode_string(key); + } + return indent(add_spaces(beautify && options.space_colon + ? [ key, ":", val ] + : [ key + ":", val ])); + }).join("," + newline); + }) + newline + indent("}"); + return obj_needs_parens ? "(" + out + ")" : out; + }, + "regexp": function(rx, mods) { + if (options.ascii_only) rx = to_ascii(rx); + return "/" + rx + "/" + mods; + }, + "array": function(elements) { + if (elements.length == 0) return "[]"; + return add_spaces([ "[", add_commas(MAP(elements, function(el, i){ + if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : ""; + return parenthesize(el, "seq"); + })), "]" ]); + }, + "stat": function(stmt) { + return stmt != null + ? make(stmt).replace(/;*\s*$/, ";") + : ";"; + }, + "seq": function() { + return add_commas(MAP(slice(arguments), make)); + }, + "label": function(name, block) { + return add_spaces([ make_name(name), ":", make(block) ]); + }, + "with": function(expr, block) { + return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); + }, + "atom": function(name) { + return make_name(name); + }, + "directive": function(dir) { + return make_string(dir) + ";"; + } + }, function(){ return make(ast) }); + + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + function make_then(th) { + if (th == null) return ";"; + if (th[0] == "do") { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 + // IE croaks with "syntax error" on code like this: + // if (foo) do ... while(cond); else ... + // we need block brackets around do/while + return make_block([ th ]); + } + var b = th; + while (true) { + var type = b[0]; + if (type == "if") { + if (!b[3]) + // no else, we must add the block + return make([ "block", [ th ]]); + b = b[3]; + } + else if (type == "while" || type == "do") b = b[2]; + else if (type == "for" || type == "for-in") b = b[4]; + else break; + } + return make(th); + }; - function needs_parens(expr) { - if (expr[0] == "function" || expr[0] == "object") { - // dot/call on a literal function requires the - // function literal itself to be parenthesized - // only if it's the first "thing" in a - // statement. This means that the parent is - // "stat", but it could also be a "seq" and - // we're the first in this "seq" and the - // parent is "stat", and so on. Messy stuff, - // but it worths the trouble. - var a = slice(w.stack()), self = a.pop(), p = a.pop(); - while (p) { - if (p[0] == "stat") return true; - if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || - ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { - self = p; - p = a.pop(); - } else { - return false; - } - } + function make_function(name, args, body, keyword, no_parens) { + var out = keyword || "function"; + if (name) { + out += " " + make_name(name); + } + out += "(" + add_commas(MAP(args, make_name)) + ")"; + out = add_spaces([ out, make_block(body) ]); + return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out; + }; + + function must_has_semicolon(node) { + switch (node[0]) { + case "with": + case "while": + return empty(node[2]) || must_has_semicolon(node[2]); + case "for": + case "for-in": + return empty(node[4]) || must_has_semicolon(node[4]); + case "if": + if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else' + if (node[3]) { + if (empty(node[3])) return true; // `else' present but empty + return must_has_semicolon(node[3]); // dive into the `else' branch + } + return must_has_semicolon(node[2]); // dive into the `then' branch + case "directive": + return true; + } + }; + + function make_block_statements(statements, noindent) { + for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { + var stat = statements[i]; + var code = make(stat); + if (code != ";") { + if (!beautify && i == last && !must_has_semicolon(stat)) { + code = code.replace(/;+\s*$/, ""); } - return !HOP(DOT_CALL_NO_PARENS, expr[0]); - }; + a.push(code); + } + } + return noindent ? a : MAP(a, indent); + }; + + function make_switch_block(body) { + var n = body.length; + if (n == 0) return "{}"; + return "{" + newline + MAP(body, function(branch, i){ + var has_body = branch[1].length > 0, code = with_indent(function(){ + return indent(branch[0] + ? add_spaces([ "case", make(branch[0]) + ":" ]) + : "default:"); + }, 0.5) + (has_body ? newline + with_indent(function(){ + return make_block_statements(branch[1]).join(newline); + }) : ""); + if (!beautify && has_body && i < n - 1) + code += ";"; + return code; + }).join(newline) + newline + indent("}"); + }; + + function make_block(statements) { + if (!statements) return ";"; + if (statements.length == 0) return "{}"; + return "{" + newline + with_indent(function(){ + return make_block_statements(statements).join(newline); + }) + newline + indent("}"); + }; + + function make_1vardef(def) { + var name = def[0], val = def[1]; + if (val != null) + name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); + return name; + }; - function make_num(num) { - var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; - if (Math.floor(num) === num) { - if (num >= 0) { - a.push("0x" + num.toString(16).toLowerCase(), // probably pointless - "0" + num.toString(8)); // same. - } else { - a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless - "-0" + (-num).toString(8)); // same. - } - if ((m = /^(.*?)(0+)$/.exec(num))) { - a.push(m[1] + "e" + m[2].length); - } - } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { - a.push(m[2] + "e-" + (m[1].length + m[2].length), - str.substr(str.indexOf("."))); - } - return best_of(a); - }; +}; - var w = ast_walker(); - var make = w.walk; - return w.with_walkers({ - "string": encode_string, - "num": make_num, - "name": make_name, - "debugger": function(){ return "debugger;" }, - "toplevel": function(statements) { - return make_block_statements(statements) - .join(newline + newline); - }, - "splice": function(statements) { - var parent = w.parent(); - if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { - // we need block brackets in this case - return make_block.apply(this, arguments); - } else { - return MAP(make_block_statements(statements, true), - function(line, i) { - // the first line is already indented - return i > 0 ? indent(line) : line; - }).join(newline); - } - }, - "block": make_block, - "var": function(defs) { - return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; - }, - "const": function(defs) { - return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; - }, - "try": function(tr, ca, fi) { - var out = [ "try", make_block(tr) ]; - if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); - if (fi) out.push("finally", make_block(fi)); - return add_spaces(out); - }, - "throw": function(expr) { - return add_spaces([ "throw", make(expr) ]) + ";"; - }, - "new": function(ctor, args) { - args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){ - return parenthesize(expr, "seq"); - })) + ")" : ""; - return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ - var w = ast_walker(), has_call = {}; - try { - w.with_walkers({ - "call": function() { throw has_call }, - "function": function() { return this } - }, function(){ - w.walk(expr); - }); - } catch(ex) { - if (ex === has_call) - return true; - throw ex; - } - }) + args ]); - }, - "switch": function(expr, body) { - return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); - }, - "break": function(label) { - var out = "break"; - if (label != null) - out += " " + make_name(label); - return out + ";"; - }, - "continue": function(label) { - var out = "continue"; - if (label != null) - out += " " + make_name(label); - return out + ";"; - }, - "conditional": function(co, th, el) { - return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", - parenthesize(th, "seq"), ":", - parenthesize(el, "seq") ]); - }, - "assign": function(op, lvalue, rvalue) { - if (op && op !== true) op += "="; - else op = "="; - return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); - }, - "dot": function(expr) { - var out = make(expr), i = 1; - if (expr[0] == "num") { - if (!/[a-f.]/i.test(out)) - out += "."; - } else if (expr[0] != "function" && needs_parens(expr)) - out = "(" + out + ")"; - while (i < arguments.length) - out += "." + make_name(arguments[i++]); - return out; - }, - "call": function(func, args) { - var f = make(func); - if (f.charAt(0) != "(" && needs_parens(func)) - f = "(" + f + ")"; - return f + "(" + add_commas(MAP(args, function(expr){ - return parenthesize(expr, "seq"); - })) + ")"; - }, - "function": make_function, - "defun": make_function, - "if": function(co, th, el) { - var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; - if (el) { - out.push("else", make(el)); - } - return add_spaces(out); - }, - "for": function(init, cond, step, block) { - var out = [ "for" ]; - init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); - cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); - step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); - var args = init + cond + step; - if (args == "; ; ") args = ";;"; - out.push("(" + args + ")", make(block)); - return add_spaces(out); - }, - "for-in": function(vvar, key, hash, block) { - return add_spaces([ "for", "(" + - (vvar ? make(vvar).replace(/;+$/, "") : make(key)), - "in", - make(hash) + ")", make(block) ]); - }, - "while": function(condition, block) { - return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); - }, - "do": function(condition, block) { - return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; - }, - "return": function(expr) { - var out = [ "return" ]; - if (expr != null) out.push(make(expr)); - return add_spaces(out) + ";"; - }, - "binary": function(operator, lvalue, rvalue) { - var left = make(lvalue), right = make(rvalue); - // XXX: I'm pretty sure other cases will bite here. - // we need to be smarter. - // adding parens all the time is the safest bet. - if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || - lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] || - lvalue[0] == "function" && needs_parens(this)) { - left = "(" + left + ")"; - } - if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || - rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && - !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { - right = "(" + right + ")"; - } - else if (!beautify && options.inline_script && (operator == "<" || operator == "<<") - && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { - right = " " + right; - } - return add_spaces([ left, operator, right ]); - }, - "unary-prefix": function(operator, expr) { - var val = make(expr); - if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) - val = "(" + val + ")"; - return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; - }, - "unary-postfix": function(operator, expr) { - var val = make(expr); - if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) - val = "(" + val + ")"; - return val + operator; - }, - "sub": function(expr, subscript) { - var hash = make(expr); - if (needs_parens(expr)) - hash = "(" + hash + ")"; - return hash + "[" + make(subscript) + "]"; - }, - "object": function(props) { - var obj_needs_parens = needs_parens(this); - if (props.length == 0) - return obj_needs_parens ? "({})" : "{}"; - var out = "{" + newline + with_indent(function(){ - return MAP(props, function(p){ - if (p.length == 3) { - // getter/setter. The name is in p[0], the arg.list in p[1][2], the - // body in p[1][3] and type ("get" / "set") in p[2]. - return indent(make_function(p[0], p[1][2], p[1][3], p[2], true)); - } - var key = p[0], val = parenthesize(p[1], "seq"); - if (options.quote_keys) { - key = encode_string(key); - } else if ((typeof key == "number" || !beautify && +key + "" == key) - && parseFloat(key) >= 0) { - key = make_num(+key); - } else if (!is_identifier(key)) { - key = encode_string(key); - } - return indent(add_spaces(beautify && options.space_colon - ? [ key, ":", val ] - : [ key + ":", val ])); - }).join("," + newline); - }) + newline + indent("}"); - return obj_needs_parens ? "(" + out + ")" : out; - }, - "regexp": function(rx, mods) { - if (options.ascii_only) rx = to_ascii(rx); - return "/" + rx + "/" + mods; - }, - "array": function(elements) { - if (elements.length == 0) return "[]"; - return add_spaces([ "[", add_commas(MAP(elements, function(el, i){ - if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : ""; - return parenthesize(el, "seq"); - })), "]" ]); - }, - "stat": function(stmt) { - return stmt != null - ? make(stmt).replace(/;*\s*$/, ";") - : ";"; - }, - "seq": function() { - return add_commas(MAP(slice(arguments), make)); - }, - "label": function(name, block) { - return add_spaces([ make_name(name), ":", make(block) ]); - }, - "with": function(expr, block) { - return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); - }, - "atom": function(name) { - return make_name(name); - }, - "directive": function(dir) { - return make_string(dir) + ";"; - } - }, function(){ return make(ast) }); - - // The squeezer replaces "block"-s that contain only a single - // statement with the statement itself; technically, the AST - // is correct, but this can create problems when we output an - // IF having an ELSE clause where the THEN clause ends in an - // IF *without* an ELSE block (then the outer ELSE would refer - // to the inner IF). This function checks for this case and - // adds the block brackets if needed. - function make_then(th) { - if (th == null) return ";"; - if (th[0] == "do") { - // https://github.com/mishoo/UglifyJS/issues/#issue/57 - // IE croaks with "syntax error" on code like this: - // if (foo) do ... while(cond); else ... - // we need block brackets around do/while - return make_block([ th ]); - } - var b = th; - while (true) { - var type = b[0]; - if (type == "if") { - if (!b[3]) - // no else, we must add the block - return make([ "block", [ th ]]); - b = b[3]; - } - else if (type == "while" || type == "do") b = b[2]; - else if (type == "for" || type == "for-in") b = b[4]; - else break; - } - return make(th); +function split_lines(code, max_line_length) { + var splits = [ 0 ]; + jsp.parse(function(){ + var next_token = jsp.tokenizer(code); + var last_split = 0; + var prev_token; + function current_length(tok) { + return tok.pos - last_split; }; - - function make_function(name, args, body, keyword, no_parens) { - var out = keyword || "function"; - if (name) { - out += " " + make_name(name); - } - out += "(" + add_commas(MAP(args, make_name)) + ")"; - out = add_spaces([ out, make_block(body) ]); - return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out; + function split_here(tok) { + last_split = tok.pos; + splits.push(last_split); }; - - function must_has_semicolon(node) { - switch (node[0]) { - case "with": - case "while": - return empty(node[2]) || must_has_semicolon(node[2]); - case "for": - case "for-in": - return empty(node[4]) || must_has_semicolon(node[4]); - case "if": - if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else' - if (node[3]) { - if (empty(node[3])) return true; // `else' present but empty - return must_has_semicolon(node[3]); // dive into the `else' branch - } - return must_has_semicolon(node[2]); // dive into the `then' branch - case "directive": - return true; + function custom(){ + var tok = next_token.apply(this, arguments); + out: { + if (prev_token) { + if (prev_token.type == "keyword") break out; } - }; - - function make_block_statements(statements, noindent) { - for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { - var stat = statements[i]; - var code = make(stat); - if (code != ";") { - if (!beautify && i == last && !must_has_semicolon(stat)) { - code = code.replace(/;+\s*$/, ""); - } - a.push(code); - } + if (current_length(tok) > max_line_length) { + switch (tok.type) { + case "keyword": + case "atom": + case "name": + case "punc": + split_here(tok); + break out; + } } - return noindent ? a : MAP(a, indent); + } + prev_token = tok; + return tok; }; - - function make_switch_block(body) { - var n = body.length; - if (n == 0) return "{}"; - return "{" + newline + MAP(body, function(branch, i){ - var has_body = branch[1].length > 0, code = with_indent(function(){ - return indent(branch[0] - ? add_spaces([ "case", make(branch[0]) + ":" ]) - : "default:"); - }, 0.5) + (has_body ? newline + with_indent(function(){ - return make_block_statements(branch[1]).join(newline); - }) : ""); - if (!beautify && has_body && i < n - 1) - code += ";"; - return code; - }).join(newline) + newline + indent("}"); - }; - - function make_block(statements) { - if (!statements) return ";"; - if (statements.length == 0) return "{}"; - return "{" + newline + with_indent(function(){ - return make_block_statements(statements).join(newline); - }) + newline + indent("}"); + custom.context = function() { + return next_token.context.apply(this, arguments); }; - - function make_1vardef(def) { - var name = def[0], val = def[1]; - if (val != null) - name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); - return name; - }; - -}; - -function split_lines(code, max_line_length) { - var splits = [ 0 ]; - jsp.parse(function(){ - var next_token = jsp.tokenizer(code); - var last_split = 0; - var prev_token; - function current_length(tok) { - return tok.pos - last_split; - }; - function split_here(tok) { - last_split = tok.pos; - splits.push(last_split); - }; - function custom(){ - var tok = next_token.apply(this, arguments); - out: { - if (prev_token) { - if (prev_token.type == "keyword") break out; - } - if (current_length(tok) > max_line_length) { - switch (tok.type) { - case "keyword": - case "atom": - case "name": - case "punc": - split_here(tok); - break out; - } - } - } - prev_token = tok; - return tok; - }; - custom.context = function() { - return next_token.context.apply(this, arguments); - }; - return custom; - }()); - return splits.map(function(pos, i){ - return code.substring(pos, splits[i + 1] || code.length); - }).join("\n"); + return custom; + }()); + return splits.map(function(pos, i){ + return code.substring(pos, splits[i + 1] || code.length); + }).join("\n"); }; /* -----[ Utilities ]----- */ function repeat_string(str, i) { - if (i <= 0) return ""; - if (i == 1) return str; - var d = repeat_string(str, i >> 1); - d += d; - if (i & 1) d += str; - return d; + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; }; function defaults(args, defs) { - var ret = {}; - if (args === true) - args = {}; - for (var i in defs) if (HOP(defs, i)) { - ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; - } - return ret; + var ret = {}; + if (args === true) + args = {}; + for (var i in defs) if (HOP(defs, i)) { + ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; + } + return ret; }; function is_identifier(name) { - return /^[a-z_$][a-z0-9_$]*$/i.test(name) - && name != "this" - && !HOP(jsp.KEYWORDS_ATOM, name) - && !HOP(jsp.RESERVED_WORDS, name) - && !HOP(jsp.KEYWORDS, name); + return /^[a-z_$][a-z0-9_$]*$/i.test(name) + && name != "this" + && !HOP(jsp.KEYWORDS_ATOM, name) + && !HOP(jsp.RESERVED_WORDS, name) + && !HOP(jsp.KEYWORDS, name); }; function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); + return Object.prototype.hasOwnProperty.call(obj, prop); }; // some utilities @@ -2064,35 +2065,35 @@ function HOP(obj, prop) { var MAP; (function(){ - MAP = function(a, f, o) { - var ret = [], top = [], i; - function doit() { - var val = f.call(o, a[i], i); - if (val instanceof AtTop) { - val = val.v; - if (val instanceof Splice) { - top.push.apply(top, val.v); - } else { - top.push(val); - } - } - else if (val != skip) { - if (val instanceof Splice) { - ret.push.apply(ret, val.v); - } else { - ret.push(val); - } - } - }; - if (a instanceof Array) for (i = 0; i < a.length; ++i) doit(); - else for (i in a) if (HOP(a, i)) doit(); - return top.concat(ret); + MAP = function(a, f, o) { + var ret = [], top = [], i; + function doit() { + var val = f.call(o, a[i], i); + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, val.v); + } else { + top.push(val); + } + } + else if (val != skip) { + if (val instanceof Splice) { + ret.push.apply(ret, val.v); + } else { + ret.push(val); + } + } }; - MAP.at_top = function(val) { return new AtTop(val) }; - MAP.splice = function(val) { return new Splice(val) }; - var skip = MAP.skip = {}; - function AtTop(val) { this.v = val }; - function Splice(val) { this.v = val }; + if (a instanceof Array) for (i = 0; i < a.length; ++i) doit(); + else for (i in a) if (HOP(a, i)) doit(); + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; })(); /* -----[ Exports ]----- */ @@ -2112,5 +2113,5 @@ exports.MAP = MAP; exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; // Local variables: -// js-indent-level: 8 +// js-indent-level: 4 // End: diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/squeeze-more.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/squeeze-more.js index 87275e5..a14bc45 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/squeeze-more.js +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/lib/squeeze-more.js @@ -8,71 +8,71 @@ var jsp = require("./parse-js"), OPERATORS = jsp.OPERATORS; function ast_squeeze_more(ast) { - var w = pro.ast_walker(), walk = w.walk, scope; - function with_scope(s, cont) { - var save = scope, ret; - scope = s; - ret = cont(); - scope = save; - return ret; - }; - function _lambda(name, args, body) { - return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; - }; - return w.with_walkers({ - "toplevel": function(body) { - return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; - }, - "function": _lambda, - "defun": _lambda, - "new": function(ctor, args) { - if (ctor[0] == "name") { - if (ctor[1] == "Array" && !scope.has("Array")) { - if (args.length != 1) { - return [ "array", args ]; - } else { - return walk([ "call", [ "name", "Array" ], args ]); - } - } else if (ctor[1] == "Object" && !scope.has("Object")) { - if (!args.length) { - return [ "object", [] ]; - } else { - return walk([ "call", [ "name", "Object" ], args ]); - } - } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) { - return walk([ "call", [ "name", ctor[1] ], args]); - } - } - }, - "call": function(expr, args) { - if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1 - && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) { - return [ "call", [ "dot", expr[1], "slice"], args]; - } - if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { - // foo.toString() ==> foo+"" - if (expr[1][0] == "string") return expr[1]; - return [ "binary", "+", expr[1], [ "string", "" ]]; - } - if (expr[0] == "name") { - if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { - return [ "array", args ]; - } - if (expr[1] == "Object" && !args.length && !scope.has("Object")) { - return [ "object", [] ]; - } - if (expr[1] == "String" && !scope.has("String")) { - return [ "binary", "+", args[0], [ "string", "" ]]; - } - } + var w = pro.ast_walker(), walk = w.walk, scope; + function with_scope(s, cont) { + var save = scope, ret; + scope = s; + ret = cont(); + scope = save; + return ret; + }; + function _lambda(name, args, body) { + return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; + }; + return w.with_walkers({ + "toplevel": function(body) { + return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; + }, + "function": _lambda, + "defun": _lambda, + "new": function(ctor, args) { + if (ctor[0] == "name") { + if (ctor[1] == "Array" && !scope.has("Array")) { + if (args.length != 1) { + return [ "array", args ]; + } else { + return walk([ "call", [ "name", "Array" ], args ]); + } + } else if (ctor[1] == "Object" && !scope.has("Object")) { + if (!args.length) { + return [ "object", [] ]; + } else { + return walk([ "call", [ "name", "Object" ], args ]); + } + } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) { + return walk([ "call", [ "name", ctor[1] ], args]); } - }, function() { - return walk(pro.ast_add_scope(ast)); - }); + } + }, + "call": function(expr, args) { + if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1 + && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) { + return [ "call", [ "dot", expr[1], "slice"], args]; + } + if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { + // foo.toString() ==> foo+"" + if (expr[1][0] == "string") return expr[1]; + return [ "binary", "+", expr[1], [ "string", "" ]]; + } + if (expr[0] == "name") { + if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { + return [ "array", args ]; + } + if (expr[1] == "Object" && !args.length && !scope.has("Object")) { + return [ "object", [] ]; + } + if (expr[1] == "String" && !scope.has("String")) { + return [ "binary", "+", args[0], [ "string", "" ]]; + } + } + } + }, function() { + return walk(pro.ast_add_scope(ast)); + }); }; exports.ast_squeeze_more = ast_squeeze_more; // Local variables: -// js-indent-level: 8 +// js-indent-level: 4 // End: diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/package.json index ac2c60c..a3d730d 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/package.json @@ -6,7 +6,7 @@ "email": "mihai.bazon@gmail.com", "url": "http://mihai.bazon.net/blog" }, - "version": "1.3.3", + "version": "1.3.4", "main": "./uglify-js.js", "bin": { "uglifyjs": "./bin/uglifyjs" @@ -21,7 +21,8 @@ "scripts": { "test": "$(which nodeunit || echo node_modules/nodeunit/bin/nodeunit) test/unit/scripts.js && test/testparser.js && test/testconsolidator.js" }, - "readme": "\n\n\n\nUglifyJS – a JavaScript parser/compressor/beautifier\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n\n
    \n\n
    \n

    UglifyJS – a JavaScript parser/compressor/beautifier

    \n\n\n\n\n
    \n

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    \n
    \n\n\n

    \nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

    \n

    \nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

    \n

    \n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

    \n

    \nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

    \n
      \n
    • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify” a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
    • \n
    • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
    • \n
    • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
        \n
      • foo[\"bar\"] ==> foo.bar\n\n
      • \n
      • remove block brackets {}\n\n
      • \n
      • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
      • \n
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
      • \n
      • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
      • \n
      • various optimizations for IF statements:\n\n
          \n
        • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
        • \n
        • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
        • \n
        • if (foo) bar(); ==> foo&&bar();\n
        • \n
        • if (!foo) bar(); ==> foo||bar();\n
        • \n
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
        • \n
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
        • \n
        \n\n
      • \n
      • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
      • \n
      • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.1 Unsafe transformations

    \n
    \n\n\n

    \nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

    \n\n
    \n\n
    \n

    1.1.1 Calls involving the global Array constructor

    \n
    \n\n\n

    \nThe following transformations occur:\n

    \n\n\n\n
    new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
    \n\n\n

    \nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

    \n

    \nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

    \n\n\n\n
    // case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.1.2 obj.toString() ==> obj+“”

    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n

    1.2 Install (NPM)

    \n
    \n\n\n

    \nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

    \n
    \n\n
    \n\n
    \n

    1.3 Install latest code from GitHub

    \n
    \n\n\n\n\n\n
    ## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4 Usage

    \n
    \n\n\n

    \nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

    \n\n\n\n
    uglifyjs [ options... ] [ filename ]\n
    \n\n\n

    \nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

    \n

    \nSupported options:\n

    \n
      \n
    • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
        \n
      • -i N or --indent N — indentation level (number of spaces)\n\n
      • \n
      • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
      • \n
      \n\n
    • \n
    • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
    • \n
    • -nm or --no-mangle — don't mangle names.\n\n
    • \n
    • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
    • \n
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
    • \n
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
    • \n
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
    • \n
    • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
    • \n
    • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
    • \n
    • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
    • \n
    • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
    • \n
    • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
    • \n
    • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
    • \n
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
    • \n
    • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
    • \n
    • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
        \n
      • foo.toString() ==> foo+\"\"\n
      • \n
      • new Array(x,…) ==> [x,…]\n
      • \n
      • new Array(x) ==> Array(x)\n\n
      • \n
      \n\n
    • \n
    • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
    • \n
    • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
    • \n
    • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
    • \n
    • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
        \n
      • put all var declarations at the start of the scope\n
      • \n
      • make sure a variable is declared only once\n
      • \n
      • discard unused function arguments\n
      • \n
      • discard unused inner (named) functions\n
      • \n
      • finally, try to merge assignments into that one var declaration, if\n possible.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.4.1 API

    \n
    \n\n\n

    \nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

    \n\n\n\n
    var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
    \n\n\n

    \nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

    \n

    \nSome of these functions take optional arguments. Here's a description:\n

    \n
      \n
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
    • \n
    • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

      \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

      \n

      \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

      \n

      \n Here's an example of what it does:\n

    • \n
    \n\n\n\n\n\n
    function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
    \n\n\n
      \n
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
        \n
      • toplevel – mangle toplevel names (by default we don't touch them).\n
      • \n
      • except – an array of names to exclude from compression.\n
      • \n
      • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
      • \n
      \n\n
    • \n
    • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
        \n
      • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
      • \n
      • dead_code (default true) which will remove unreachable code.\n\n
      • \n
      \n\n
    • \n
    • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
        \n
      • beautify: false – pass true if you want indented output\n
      • \n
      • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
      • \n
      • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
      • \n
      • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
      • \n
      • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
      • \n
      • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
      • \n
      • inline_script: false – pass true to escape occurrences of\n </script in strings\n
      • \n
      \n\n
    • \n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4.2 Beautifier shortcoming – no more comments

    \n
    \n\n\n

    \nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

    \n

    \nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

    \n
    \n\n
    \n\n
    \n

    1.4.3 Use as a code pre-processor

    \n
    \n\n\n

    \nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

    \n

    \nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

    \n\n\n\n
    CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
    \n\n\n

    \nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

    \n

    \nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

    \n

    \nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

    \n

    \nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

    \n

    \nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

    \n
    \n
    \n\n
    \n\n
    \n

    1.5 Compression – how good is it?

    \n
    \n\n\n

    \nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

    \n

    \nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    \n\n\n
    \n\n
    \n\n
    \n

    1.6 Bugs?

    \n
    \n\n\n

    \nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

    \n

    \nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

    \n

    \nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

    \n
    \n\n
    \n\n
    \n

    1.7 Links

    \n
    \n\n\n\n\n\n
    \n\n
    \n\n
    \n

    1.8 License

    \n
    \n\n\n

    \nUglifyJS is released under the BSD license:\n

    \n\n\n\n
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
    \n\n\n
    \n

    Footnotes:

    \n
    \n

    1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n

    Date: 2011-12-09 14:59:08 EET

    \n

    Author: Mihai Bazon

    \n

    Org version 7.7 with Emacs version 23

    \nValidate XHTML 1.0\n\n
    \n\n\n", - "_id": "uglify-js@1.3.3", + "readme": "\n\n\n\nUglifyJS – a JavaScript parser/compressor/beautifier\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n\n
    \n\n
    \n

    UglifyJS – a JavaScript parser/compressor/beautifier

    \n\n\n\n\n
    \n

    1 NEW: UglifyJS2

    \n
    \n\n\n

    \nI started working on UglifyJS's successor, version 2. It's almost a full\nrewrite (except for the parser which is heavily modified, everything else\nstarts from scratch). I've detailed my reasons in the README, see the\nproject page.\n

    \n

    \nhttps://github.com/mishoo/UglifyJS2\n

    \n

    \nVersion 1 will continue to be maintained for fixing show-stopper bugs, but\nno new features should be expected.\n

    \n

    \nPlease help me focus on version 2 by making a donation!\n

    \n
    \n\n
    \n\n
    \n

    2 UglifyJS — a JavaScript parser/compressor/beautifier

    \n
    \n\n\n

    \nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

    \n

    \nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

    \n

    \n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

    \n

    \nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

    \n
      \n
    • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify” a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
    • \n
    • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
    • \n
    • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
        \n
      • foo[\"bar\"] ==> foo.bar\n\n
      • \n
      • remove block brackets {}\n\n
      • \n
      • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
      • \n
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
      • \n
      • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
      • \n
      • various optimizations for IF statements:\n\n
          \n
        • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
        • \n
        • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
        • \n
        • if (foo) bar(); ==> foo&&bar();\n
        • \n
        • if (!foo) bar(); ==> foo||bar();\n
        • \n
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
        • \n
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
        • \n
        \n\n
      • \n
      • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
      • \n
      • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    2.1 Unsafe transformations

    \n
    \n\n\n

    \nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

    \n\n
    \n\n
    \n

    2.1.1 Calls involving the global Array constructor

    \n
    \n\n\n

    \nThe following transformations occur:\n

    \n\n\n\n
    new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
    \n\n\n

    \nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

    \n

    \nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

    \n\n\n\n
    // case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
    \n\n\n
    \n\n
    \n\n
    \n

    2.1.2 obj.toString() ==> obj+“”

    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n

    2.2 Install (NPM)

    \n
    \n\n\n

    \nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

    \n
    \n\n
    \n\n
    \n

    2.3 Install latest code from GitHub

    \n
    \n\n\n\n\n\n
    ## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
    \n\n\n
    \n\n
    \n\n
    \n

    2.4 Usage

    \n
    \n\n\n

    \nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

    \n\n\n\n
    uglifyjs [ options... ] [ filename ]\n
    \n\n\n

    \nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

    \n

    \nSupported options:\n

    \n
      \n
    • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
        \n
      • -i N or --indent N — indentation level (number of spaces)\n\n
      • \n
      • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
      • \n
      \n\n
    • \n
    • -c or ----consolidate-primitive-values — consolidates null, Boolean,\n and String values. Known as aliasing in the Closure Compiler. Worsens the\n data compression ratio of gzip.\n\n
    • \n
    • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
    • \n
    • -nm or --no-mangle — don't mangle names.\n\n
    • \n
    • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
    • \n
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
    • \n
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
    • \n
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
    • \n
    • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
    • \n
    • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
    • \n
    • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
    • \n
    • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
    • \n
    • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
    • \n
    • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
    • \n
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
    • \n
    • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
    • \n
    • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
        \n
      • foo.toString() ==> foo+\"\"\n
      • \n
      • new Array(x,…) ==> [x,…]\n
      • \n
      • new Array(x) ==> Array(x)\n\n
      • \n
      \n\n
    • \n
    • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
    • \n
    • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
    • \n
    • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
    • \n
    • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
        \n
      • put all var declarations at the start of the scope\n
      • \n
      • make sure a variable is declared only once\n
      • \n
      • discard unused function arguments\n
      • \n
      • discard unused inner (named) functions\n
      • \n
      • finally, try to merge assignments into that one var declaration, if\n possible.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    2.4.1 API

    \n
    \n\n\n

    \nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

    \n\n\n\n
    var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
    \n\n\n

    \nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

    \n

    \nSome of these functions take optional arguments. Here's a description:\n

    \n
      \n
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
    • \n
    • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

      \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

      \n

      \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

      \n

      \n Here's an example of what it does:\n

    • \n
    \n\n\n\n\n\n
    function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
    \n\n\n
      \n
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
        \n
      • toplevel – mangle toplevel names (by default we don't touch them).\n
      • \n
      • except – an array of names to exclude from compression.\n
      • \n
      • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
      • \n
      \n\n
    • \n
    • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
        \n
      • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
      • \n
      • dead_code (default true) which will remove unreachable code.\n\n
      • \n
      \n\n
    • \n
    • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
        \n
      • beautify: false – pass true if you want indented output\n
      • \n
      • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
      • \n
      • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
      • \n
      • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
      • \n
      • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
      • \n
      • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
      • \n
      • inline_script: false – pass true to escape occurrences of\n </script in strings\n
      • \n
      \n\n
    • \n
    \n\n\n
    \n\n
    \n\n
    \n

    2.4.2 Beautifier shortcoming – no more comments

    \n
    \n\n\n

    \nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

    \n

    \nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

    \n
    \n\n
    \n\n
    \n

    2.4.3 Use as a code pre-processor

    \n
    \n\n\n

    \nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

    \n

    \nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

    \n\n\n\n
    CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
    \n\n\n

    \nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

    \n

    \nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

    \n

    \nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

    \n

    \nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

    \n

    \nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

    \n
    \n
    \n\n
    \n\n
    \n

    2.5 Compression – how good is it?

    \n
    \n\n\n

    \nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

    \n

    \nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    \n\n\n
    \n\n
    \n\n
    \n

    2.6 Bugs?

    \n
    \n\n\n

    \nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

    \n

    \nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

    \n

    \nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

    \n
    \n\n
    \n\n
    \n

    2.7 Links

    \n
    \n\n\n\n\n\n
    \n\n
    \n\n
    \n

    2.8 License

    \n
    \n\n\n

    \nUglifyJS is released under the BSD license:\n

    \n\n\n\n
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
    \n\n\n
    \n

    Footnotes:

    \n
    \n

    1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n

    Date: 2012-08-27 12:38:12 EEST

    \n

    Author: Mihai Bazon

    \n

    Org version 7.7 with Emacs version 23

    \nValidate XHTML 1.0\n\n
    \n\n\n", + "readmeFilename": "README.html", + "_id": "uglify-js@1.3.4", "_from": "uglify-js@~1.3.3" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/expected/div-with-regexp.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/expected/div-with-regexp.js new file mode 100644 index 0000000..1d2a581 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/expected/div-with-regexp.js @@ -0,0 +1 @@ +print(a/ /[a-z]/) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/div-with-regexp.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/div-with-regexp.js new file mode 100644 index 0000000..872a21f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/div-with-regexp.js @@ -0,0 +1 @@ +print(a / /[a-z]/); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/package.json index 2e8bec3..af696ca 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/package.json @@ -66,6 +66,7 @@ } ], "readme": "# Underscore.string [![Build Status](https://secure.travis-ci.org/epeli/underscore.string.png?branch=master)](http://travis-ci.org/epeli/underscore.string) #\n\n\n\nJavascript lacks complete string manipulation operations.\nThis an attempt to fill that gap. List of build-in methods can be found\nfor example from [Dive Into JavaScript][d].\n\n[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object\n\n\nAs name states this an extension for [Underscore.js][u], but it can be used\nindependently from **_s**-global variable. But with Underscore.js you can\nuse Object-Oriented style and chaining:\n\n[u]: http://documentcloud.github.com/underscore/\n\n```javascript\n_(\" epeli \").chain().trim().capitalize().value()\n=> \"Epeli\"\n```\n\n## Download ##\n\n * [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb*\n * [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb*\n\n\n## Node.js installation ##\n\n**npm package**\n\n npm install underscore.string\n\n**Standalone usage**:\n\n```javascript\nvar _s = require('underscore.string');\n```\n\n**Integrate with Underscore.js**:\n\n```javascript\nvar _ = require('underscore');\n\n// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains)\n_.str = require('underscore.string');\n\n// Mix in non-conflict functions to Underscore namespace if you want\n_.mixin(_.str.exports());\n\n// All functions, include conflict, will be available through _.str object\n_.str.include('Underscore.string', 'string'); // => true\n```\n\n## String Functions ##\n\nFor availability of functions in this way you need to mix in Underscore.string functions:\n\n```javascript\n_.mixin(_.string.exports());\n```\n\notherwise functions from examples will be available through _.string or _.str objects:\n\n```javascript\n_.str.capitalize('epeli')\n=> \"Epeli\"\n```\n\n**capitalize** _.capitalize(string)\n\nConverts first letter of the string to uppercase and the rest of the string to lower case.\n\n```javascript\n_.capitalize(\"foo Bar\")\n=> \"Foo bar\"\n```\n\n**chop** _.chop(string, step)\n\n```javascript\n_.chop('whitespace', 3)\n=> ['whi','tes','pac','e']\n```\n\n**clean** _.clean(str)\n\nCompress some whitespaces to one.\n\n```javascript\n_.clean(\" foo bar \")\n=> 'foo bar'\n```\n\n**chars** _.chars(str)\n\n```javascript\n_.chars('Hello')\n=> ['H','e','l','l','o']\n```\n\n**includes** _.includes(string, substring)\n\nTests if string contains a substring.\n\n```javascript\n_.includes(\"foobar\", \"ob\")\n=> true\n```\n\n**include** available only through _.str object, because Underscore has function with the same name.\n\n```javascript\n_.str.include(\"foobar\", \"ob\")\n=> true\n```\n\n**includes** function was removed\n\nBut you can create it in this way, for compatibility with previous versions:\n\n```javascript\n_.includes = _.str.include\n```\n\n**count** _.count(string, substring)\n\n```javascript\n_('Hello world').count('l')\n=> 3\n```\n\n**escapeHTML** _.escapeHTML(string)\n\nConverts HTML special characters to their entity equivalents.\n\n```javascript\n_('
    Blah blah blah
    ').escapeHTML();\n=> '<div>Blah blah blah</div>'\n```\n\n**unescapeHTML** _.unescapeHTML(string)\n\nConverts entity characters to HTML equivalents.\n\n```javascript\n_('<div>Blah blah blah</div>').unescapeHTML();\n=> '
    Blah blah blah
    '\n```\n\n**insert** _.insert(string, index, substing)\n\n```javascript\n_('Hello ').insert(6, 'world')\n=> 'Hello world'\n```\n\n**isBlank** _.isBlank(string)\n\n```javascript\n_('').isBlank(); // => true\n_('\\n').isBlank(); // => true\n_(' ').isBlank(); // => true\n_('a').isBlank(); // => false\n```\n\n**join** _.join(separator, *strings)\n\nJoins strings together with given separator\n\n```javascript\n_.join(\" \", \"foo\", \"bar\")\n=> \"foo bar\"\n```\n\n**lines** _.lines(str)\n\n```javascript\n_.lines(\"Hello\\nWorld\")\n=> [\"Hello\", \"World\"]\n```\n\n**reverse** available only through _.str object, because Underscore has function with the same name.\n\nReturn reversed string:\n\n```javascript\n_.str.reverse(\"foobar\")\n=> 'raboof'\n```\n\n**splice** _.splice(string, index, howmany, substring)\n\nLike a array splice.\n\n```javascript\n_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli')\n=> 'https://edtsech@bitbucket.org/epeli/underscore.strings'\n```\n\n**startsWith** _.startsWith(string, starts)\n\nThis method checks whether string starts with starts.\n\n```javascript\n_(\"image.gif\").startsWith(\"image\")\n=> true\n```\n\n**endsWith** _.endsWith(string, ends)\n\nThis method checks whether string ends with ends.\n\n```javascript\n_(\"image.gif\").endsWith(\"gif\")\n=> true\n```\n\n**succ** _.succ(str)\n\nReturns the successor to str.\n\n```javascript\n_('a').succ()\n=> 'b'\n\n_('A').succ()\n=> 'B'\n```\n\n**supplant**\n\nSupplant function was removed, use Underscore.js [template function][p].\n\n[p]: http://documentcloud.github.com/underscore/#template\n\n**strip** alias for *trim*\n\n**lstrip** alias for *ltrim*\n\n**rstrip** alias for *rtrim*\n\n**titleize** _.titleize(string)\n\n```javascript\n_('my name is epeli').titleize()\n=> 'My Name Is Epeli'\n```\n\n**camelize** _.camelize(string)\n\nConverts underscored or dasherized string to a camelized one\n\n```javascript\n_('-moz-transform').camelize()\n=> 'MozTransform'\n```\n\n**classify** _.classify(string)\n\nConverts string to camelized class name\n\n```javascript\n_('some_class_name').classify()\n=> 'SomeClassName'\n```\n\n**underscored** _.underscored(string)\n\nConverts a camelized or dasherized string into an underscored one\n\n```javascript\n_('MozTransform').underscored()\n=> 'moz_transform'\n```\n\n**dasherize** _.dasherize(string)\n\nConverts a underscored or camelized string into an dasherized one\n\n```javascript\n_('MozTransform').dasherize()\n=> '-moz-transform'\n```\n\n**humanize** _.humanize(string)\n\nConverts an underscored, camelized, or dasherized string into a humanized one.\nAlso removes beginning and ending whitespace, and removes the postfix '_id'.\n\n```javascript\n_(' capitalize dash-CamelCase_underscore trim ').humanize()\n=> 'Capitalize dash camel case underscore trim'\n```\n\n**trim** _.trim(string, [characters])\n\ntrims defined characters from begining and ending of the string.\nDefaults to whitespace characters.\n\n```javascript\n_.trim(\" foobar \")\n=> \"foobar\"\n\n_.trim(\"_-foobar-_\", \"_-\")\n=> \"foobar\"\n```\n\n\n**ltrim** _.ltrim(string, [characters])\n\nLeft trim. Similar to trim, but only for left side.\n\n\n**rtrim** _.rtrim(string, [characters])\n\nRight trim. Similar to trim, but only for right side.\n\n**truncate** _.truncate(string, length, truncateString)\n\n```javascript\n_('Hello world').truncate(5)\n=> 'Hello...'\n\n_('Hello').truncate(10)\n=> 'Hello'\n```\n\n**prune** _.prune(string, length, pruneString)\n\nElegant version of truncate.\nMakes sure the pruned string does not exceed the original length.\nAvoid half-chopped words when truncating.\n\n```javascript\n_('Hello, world').prune(5)\n=> 'Hello...'\n\n_('Hello, world').prune(8)\n=> 'Hello...'\n\n_('Hello, world').prune(5, ' (read a lot more)')\n=> 'Hello, world' (as adding \"(read a lot more)\" would be longer than the original string)\n\n_('Hello, cruel world').prune(15)\n=> 'Hello, cruel...'\n\n_('Hello').prune(10)\n=> 'Hello'\n```\n\n**words** _.words(str, delimiter=\" \")\n\nSplit string by delimiter (String or RegExp), ' ' by default.\n\n```javascript\n_.words(\"I love you\")\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\"I_love_you\", \"_\")\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\"I-love-you\", /-/)\n=> [\"I\",\"love\",\"you\"]\n```\n\n**sprintf** _.sprintf(string format, *arguments)\n\nC like string formatting.\nCredits goes to [Alexandru Marasteanu][o].\nFor more detailed documentation, see the [original page][o].\n\n[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript\n\n```javascript\n_.sprintf(\"%.1f\", 1.17)\n\"1.2\"\n```\n\n**pad** _.pad(str, length, [padStr, type])\n\npads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`\" \"`). `padStr` is truncated to a single character if necessary.\n\n```javascript\n_.pad(\"1\", 8)\n-> \" 1\";\n\n_.pad(\"1\", 8, '0')\n-> \"00000001\";\n\n_.pad(\"1\", 8, '0', 'right')\n-> \"10000000\";\n\n_.pad(\"1\", 8, '0', 'both')\n-> \"00001000\";\n\n_.pad(\"1\", 8, 'bleepblorp', 'both')\n-> \"bbbb1bbb\";\n```\n\n**lpad** _.lpad(str, length, [padStr])\n\nleft-pad a string. Alias for `pad(str, length, padStr, 'left')`\n\n```javascript\n_.lpad(\"1\", 8, '0')\n-> \"00000001\";\n```\n\n**rpad** _.rpad(str, length, [padStr])\n\nright-pad a string. Alias for `pad(str, length, padStr, 'right')`\n\n```javascript\n_.rpad(\"1\", 8, '0')\n-> \"10000000\";\n```\n\n**lrpad** _.lrpad(str, length, [padStr])\n\nleft/right-pad a string. Alias for `pad(str, length, padStr, 'both')`\n\n```javascript\n_.lrpad(\"1\", 8, '0')\n-> \"00001000\";\n```\n\n**center** alias for **lrpad**\n\n**ljust** alias for *rpad*\n\n**rjust** alias for *lpad*\n\n**toNumber** _.toNumber(string, [decimals])\n\nParse string to number. Returns NaN if string can't be parsed to number.\n\n```javascript\n_('2.556').toNumber()\n=> 3\n\n_('2.556').toNumber(1)\n=> 2.6\n```\n\n**strRight** _.strRight(string, pattern)\n\nSearches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strRight('_')\n=> \"is_a_test_string\";\n```\n\n**strRightBack** _.strRightBack(string, pattern)\n\nSearches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strRightBack('_')\n=> \"string\";\n```\n\n**strLeft** _.strLeft(string, pattern)\n\nSearches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strLeft('_')\n=> \"This\";\n```\n\n**strLeftBack** _.strLeftBack(string, pattern)\n\nSearches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strLeftBack('_')\n=> \"This_is_a_test\";\n```\n\n**stripTags**\n\nRemoves all html tags from string.\n\n```javascript\n_('a link').stripTags()\n=> 'a link'\n\n_('a link').stripTags()\n=> 'a linkalert(\"hello world!\")'\n```\n\n**toSentence** _.toSentence(array, [delimiter, lastDelimiter])\n\nJoin an array into a human readable sentence.\n\n```javascript\n_.toSentence(['jQuery', 'Mootools', 'Prototype'])\n=> 'jQuery, Mootools and Prototype';\n\n_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ')\n=> 'jQuery, Mootools unt Prototype';\n```\n\n**repeat** _.repeat(string, count, [separator])\n\nRepeats a string count times.\n\n```javascript\n_.repeat(\"foo\", 3)\n=> 'foofoofoo';\n\n_.repeat(\"foo\", 3, \"bar\")\n=> 'foobarfoobarfoo'\n```\n\n**slugify** _.slugify(string)\n\nTransform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash.\n\n```javascript\n_.slugify(\"Un éléphant à l'orée du bois\")\n=> 'un-elephant-a-loree-du-bois';\n```\n\n***Caution: this function is charset dependent***\n\n## Roadmap ##\n\nAny suggestions or bug reports are welcome. Just email me or more preferably open an issue.\n\n## Changelog ##\n\n### 2.0.0 ###\n\n* Added prune, humanize functions\n* Added _.string (_.str) namespace for Underscore.string library\n* Removed includes function\n\n#### Problems\n\nWe lose two things for `include` and `reverse` methods from `_.string`:\n\n* Calls like `_('foobar').include('bar')` aren't available;\n* Chaining isn't available too.\n\nBut if you need this functionality you can create aliases for conflict functions which will be convenient for you:\n\n```javascript\n_.mixin({\n includeString: _.str.include,\n reverseString: _.str.reverse\n})\n\n// Now wrapper calls and chaining are available.\n_('foobar').chain().reverseString().includeString('rab').value()\n```\n\n#### Standalone Usage\n\nIf you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias\nBut of course you can just reassign `_` variable with `_.string`\n\n```javascript\n_ = _.string\n```\n### 2.1.1###\n\n* Fixed words method bug\n* Added classify method\n\n### 2.1.0 ###\n\n* AMD support\n* Added toSentence method\n* Added slugify method\n* Lots of speed optimizations\n\n### 2.0.0 ###\n\nFor upgrading to this version you need to mix in Underscore.string library to Underscore object:\n\n```javascript\n_.mixin(_.string.exports());\n```\n\nand all non-conflict Underscore.string functions will be available through Underscore object.\nAlso function `includes` has been removed, you should replace this function by `_.str.include`\nor create alias `_.includes = _.str.include` and all your code will work fine.\n\n### 1.1.6 ###\n\n* Fixed reverse and truncate\n* Added isBlank, stripTags, inlude(alias for includes)\n* Added uglifier compression\n\n### 1.1.5 ###\n\n* Added strRight, strRightBack, strLeft, strLeftBack\n\n### 1.1.4 ###\n\n* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust\n* Integration with Underscore 1.1.6\n\n### 1.1.3 ###\n\n* Added methods: underscored, camelize, dasherize\n* Support newer version of npm\n\n### 1.1.2 ###\n\n* Created functions: lines, chars, words functions\n\n### 1.0.2 ###\n\n* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible)\n* Removed 'reverse' function, because this function override underscore.js 'reverse'\n\n## Contribute ##\n\n* Fork & pull request. Don't forget about tests.\n* If you planning add some feature please create issue before.\n\nOtherwise changes will be rejected.\n\n## Contributors list ##\n\n* Esa-Matti Suuronen (),\n* Edward Tsech ,\n* Sasha Koss (),\n* Vladimir Dronnikov ,\n* Pete Kruckenberg (),\n* Paul Chavard (),\n* Ed Finkler ()\n* Pavel Pravosud \n* Anton Lindqvist ()\n\n## Licence ##\n\nThe MIT License\n\nCopyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies 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,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n", + "readmeFilename": "README.markdown", "_id": "underscore.string@2.1.1", "_from": "underscore.string@~2.1.1" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/package.json index 7505d69..f2e3a0e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/package.json @@ -21,6 +21,7 @@ "main": "underscore.js", "version": "1.2.4", "readme": " __ \n /\\ \\ \n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ \n/\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \n\\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ \n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\n \n \n\nUnderscore.js is a utility-belt library for JavaScript that provides \nsupport for the usual functional suspects (each, map, reduce, filter...) \nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://documentcloud.github.com/underscore/\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n", + "readmeFilename": "README", "_id": "underscore@1.2.4", "_from": "underscore@~1.2.4" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/package.json b/node_modules/grunt-coffee/node_modules/grunt/package.json index efaf893..2056124 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/package.json +++ b/node_modules/grunt-coffee/node_modules/grunt/package.json @@ -1,23 +1,23 @@ { "name": "grunt", "description": "A task-based command line build tool for JavaScript projects.", - "version": "0.3.15", + "version": "0.3.17", "author": { "name": "\"Cowboy\" Ben Alman", "url": "http://benalman.com/" }, - "homepage": "http://github.com/cowboy/grunt", + "homepage": "http://github.com/gruntjs/grunt", "repository": { "type": "git", - "url": "git://github.com/cowboy/grunt.git" + "url": "git://github.com/gruntjs/grunt.git" }, "bugs": { - "url": "http://github.com/cowboy/grunt/issues" + "url": "http://github.com/gruntjs/grunt/issues" }, "licenses": [ { "type": "MIT", - "url": "http://github.com/cowboy/grunt/blob/master/LICENSE-MIT" + "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } ], "main": "lib/grunt", @@ -56,7 +56,7 @@ "dateformat": "1.0.2-1.2.3", "glob-whatev": "~0.1.4", "hooker": "~0.2.3", - "jshint": "~0.5.9", + "jshint": "~0.9.1", "nodeunit": "~0.7.4", "nopt": "~1.0.10", "prompt": "~0.1.12", @@ -68,7 +68,8 @@ "gzip-js": "~0.3.1" }, "devDependencies": {}, - "readme": "# grunt\nGrunt is a task-based command line build tool for JavaScript projects.\n\n_Grunt is currently in beta. While I'm already using it on multiple projects, it might have a minor issue or two. And things might change before its final release, based on your feedback. Please try it out in a project, and [make suggestions][issues] or [report bugs][issues]!_\n\n## Getting started\nBe sure to read the [getting started guide](/cowboy/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project. In addition, check out the [example gruntfiles](/cowboy/grunt/blob/master/docs/example_gruntfiles.md) which highlight a number of fairly common configurations.\n\n## Built-in tasks\nAs of now, grunt has the following predefined tasks that you can use in your project:\n\n* [concat](/cowboy/grunt/blob/master/docs/task_concat.md) - Concatenate files.\n* [init](/cowboy/grunt/blob/master/docs/task_init.md) - Generate project scaffolding from a predefined template.\n* [lint](/cowboy/grunt/blob/master/docs/task_lint.md) - Validate files with [JSHint][jshint].\n* [min](/cowboy/grunt/blob/master/docs/task_min.md) - Minify files with [UglifyJS][uglify].\n* [qunit](/cowboy/grunt/blob/master/docs/task_qunit.md) - Run [QUnit][qunit] unit tests in a headless [PhantomJS][phantom] instance.\n* [server](/cowboy/grunt/blob/master/docs/task_server.md) - Start a static web server.\n* test - Run unit tests with [nodeunit][nodeunit].\n* watch - Run predefined tasks whenever watched files change.\n\n_(More documentation forthcoming)_\n\n## Custom tasks\nIn addition to the built-in tasks, you can create your own tasks. Don't like a built-in task's default behavior? Override it. Check out the [grunt API documentation](/cowboy/grunt/blob/master/docs/api.md) and the [built-in tasks source](/cowboy/grunt/blob/master/tasks) for everything you need to know about creating custom tasks.\n\n## Documentation\nTake a look at the [documentation table of contents][docs] for all the things.\n\n## Why does grunt exist?\nDoing all this stuff manually is a total pain, and building all this stuff into a gigantic Makefile / Jakefile / Cakefile / Rakefile / ?akefile that's maintained across all my projects was also becoming a total pain. Since I always found myself performing the same tasks over and over again, for every project, it made sense to build a task-based build tool.\n\nBeing primarily a JavaScript developer, I decided to use [Node.js][node] and [npm][npm] because the dependencies I most care about ([JSHint][jshint] and [UglifyJS][uglify]) were already npm modules. That being said, while Node.js was designed to support highly-concurrent asynchronous-IO-driven web servers, it was clearly NOT designed to make command-line build tools. But none of that matters, because grunt works. Just install it and see.\n\n## Installing grunt\n\nGrunt is available as an [npm][npm] module. If you install grunt globally via `npm install -g grunt`, it will be available for use in all of your projects. Once grunt has been installed, you can type `grunt --help` at the command line for more information. And if you want to see grunt \"grunt\" itself, cd into grunt's directory and type `grunt`\n\n_Note: in Windows, you may need to run grunt as `grunt.cmd`. See the [FAQ](/cowboy/grunt/blob/master/docs/faq.md) for more Windows-specific information._\n\nFor projects already using grunt, you're done. Otherwise, if you're adding grunt to an existing project or starting from scratch, check out the [getting started guide](/cowboy/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project.\n\n## Release History\n_(Until v1.0.0, this will only be updated when major or breaking changes are made)_\n\n* 2012/09/04 - v0.3.15 - Fixing a minor problem with renaming multi tasks.\n* 2012/08/29 - v0.3.14 - Grunt plugins lacking package.json keywords should work again.\n* 2012/08/27 - v0.3.13 - Fixed Node.js 0.8.x path.existsSync warning. Updated connect, nodeunit, uglify-js deps to latest. Updated docs. Grunt plugins generated with init:gruntplugin no longer include grunt as a dependency. Added preliminary support for \"collection\" plugins.\n* 2012/07/30 - v0.3.12 - Fixing a bug in node 0.8.x where utils.spawn would terminate before receiving all child stdout.\n* 2012/06/25 - v0.3.10 - Updating a few dependencies to work with node 0.8.x (0.6.x should still work).\n* 2012/04/18 - v0.3.9 - The min task (via the uglify helper) now appends a semicolon to the end of the generated source.\n* 2012/04/06 - v0.3.8 - Init template tweaks. Anchor links added to docs, along with grunt-internal docs task to generate them. The watch task now supports multiple targets with separate wildcards and tasks. Locally-installed grunt will override global grunt even when run from global \"grunt\" script.\n* 2012/04/01 - v0.3.7 - Tweaked the behavior of the init template `exports.warnOn` property and added more init template documentation. Fixed duplicate PhantomJS debug output in qunit task. Added useful nodeunit and qunit comments into init template generated test .js files.\n* 2012/03/28 - v0.3.6 - Fixed a `--help` screen issue, a few grunt plugin related issues, and attempted to improve the overall grunt plugin docs and API.\n* 2012/03/27 - v0.3.5 - Fixed a handful of weird Windows issues. Changed default m/d/yyyy dates to yyyy-mm-dd ISO 8601. Fixed some init task bugs, docs errata, and added a lot more content to the init task docs.\n* 2012/03/26 - v0.3.3 - Added a \"gruntfile\" init template. Create a basic gruntfile in seconds with `grunt init:gruntfile`. A few other minor fixes.\n* 2012/03/25 - v0.3.2 - Init tasks can now specify a file matching wildcard for the initial \"files exist\" warning. The jQuery init template now has jQuery 1.7.2. Fixed a bug in the `task.expand*` methods.\n* 2012/03/25 - v0.3.1 - Added a few methods. Substantially reworked the init task and templates.\n* 2012/03/23 - v0.3.0 - Too many changes to list. But in brief: completely reorganized the API, removed all globals, added docs and examples for nearly everything, built a preliminary plugin system (that still needs to be tested). PLEASE RTFM OK? THX U.\n* 2012/02/03 - v0.2.14 - Added a server task (which starts a static webserver for your tasks). The qunit task now uses PhantomJS instead of Zombie.js (4768 of 4971 jQuery unit test pass, neat), and supports both file wildcards as well as http:// or https:// urls. (static webserver, anyone?). Grunt should no longer \"hang\" when done.\n* 2012/01/29 - v0.2.5 - Added a \"qunit\" task as well as an init \"jquery\" template (as of now, there are also \"node\" and \"commonjs\" init templates).\n* 2012/01/22 - v0.2.1 - Removed handlebars, templates are universally handled by underscore now. Changed init task template tags from <% %> to {% %}. Banners beginning with /*! will no longer be stripped.\n* 2012/01/22 - v0.2.0 - Added \"init\" task with a sample template, reworked a lot of code. Hopefully it's backwards-compatible.\n* 2012/01/11 - v0.1.0 - Initial release.\n\n## License\nCopyright (c) 2012 \"Cowboy\" Ben Alman \nLicensed under the MIT license. \n\n\n\n[docs]: /cowboy/grunt/blob/master/docs/toc.md\n[docs-init]: /cowboy/grunt/blob/master/docs/task_init.md\n[issues]: /cowboy/grunt/issues\n\n[node]: http://nodejs.org/\n[npm]: http://npmjs.org/\n[jshint]: http://www.jshint.com/\n[uglify]: https://github.com/mishoo/UglifyJS/\n[nodeunit]: https://github.com/caolan/nodeunit\n[qunit]: http://docs.jquery.com/QUnit\n[phantom]: http://www.phantomjs.org/\n", - "_id": "grunt@0.3.15", + "readme": "# grunt\nGrunt is a task-based command line build tool for JavaScript projects.\n\n_Grunt is currently in beta. While I'm already using it on multiple projects, it might have a minor issue or two. And things might change before its final release, based on your feedback. Please try it out in a project, and [make suggestions][issues] or [report bugs][issues]!_\n\n## Getting started\nBe sure to read the [getting started guide](/gruntjs/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project. In addition, check out the [example gruntfiles](/gruntjs/grunt/blob/master/docs/example_gruntfiles.md) which highlight a number of fairly common configurations.\n\n## Built-in tasks\nAs of now, grunt has the following predefined tasks that you can use in your project:\n\n* [concat](/gruntjs/grunt/blob/master/docs/task_concat.md) - Concatenate files.\n* [init](/gruntjs/grunt/blob/master/docs/task_init.md) - Generate project scaffolding from a predefined template.\n* [lint](/gruntjs/grunt/blob/master/docs/task_lint.md) - Validate files with [JSHint][jshint].\n* [min](/gruntjs/grunt/blob/master/docs/task_min.md) - Minify files with [UglifyJS][uglify].\n* [qunit](/gruntjs/grunt/blob/master/docs/task_qunit.md) - Run [QUnit][qunit] unit tests in a headless [PhantomJS][phantom] instance.\n* [server](/gruntjs/grunt/blob/master/docs/task_server.md) - Start a static web server.\n* test - Run unit tests with [nodeunit][nodeunit].\n* watch - Run predefined tasks whenever watched files change.\n\n_(More documentation forthcoming)_\n\n## Custom tasks\nIn addition to the built-in tasks, you can create your own tasks. Don't like a built-in task's default behavior? Override it. Check out the [grunt API documentation](/gruntjs/grunt/blob/master/docs/api.md) and the [built-in tasks source](/gruntjs/grunt/blob/master/tasks) for everything you need to know about creating custom tasks.\n\n## Documentation\nTake a look at the [documentation table of contents][docs] for all the things.\n\n## Why does grunt exist?\nDoing all this stuff manually is a total pain, and building all this stuff into a gigantic Makefile / Jakefile / Cakefile / Rakefile / ?akefile that's maintained across all my projects was also becoming a total pain. Since I always found myself performing the same tasks over and over again, for every project, it made sense to build a task-based build tool.\n\nBeing primarily a JavaScript developer, I decided to use [Node.js][node] and [npm][npm] because the dependencies I most care about ([JSHint][jshint] and [UglifyJS][uglify]) were already npm modules. That being said, while Node.js was designed to support highly-concurrent asynchronous-IO-driven web servers, it was clearly NOT designed to make command-line build tools. But none of that matters, because grunt works. Just install it and see.\n\n## Installing grunt\n\nGrunt is available as an [npm][npm] module. If you install grunt globally via `npm install -g grunt`, it will be available for use in all of your projects. Once grunt has been installed, you can type `grunt --help` at the command line for more information. And if you want to see grunt \"grunt\" itself, cd into grunt's directory and type `grunt`\n\n_Note: in Windows, you may need to run grunt as `grunt.cmd`. See the [FAQ](/gruntjs/grunt/blob/master/docs/faq.md) for more Windows-specific information._\n\nFor projects already using grunt, you're done. Otherwise, if you're adding grunt to an existing project or starting from scratch, check out the [getting started guide](/gruntjs/grunt/blob/master/docs/getting_started.md), which is a complete guide to configuring grunt for your project.\n\n## Release History\n_(Until v1.0.0, this will only be updated when major or breaking changes are made)_\n\n* 2012/10/15 - v0.3.17 - Updating JSHint to 0.9.1. Better stack traces. And a few QUnit task fixes.\n* 2012/10/01 - v0.3.16 - Updated URLs to reflect new website and source location. Tweaks to the \"jquery\" and \"commonjs\" init templates. Fixed an issue when exiting due to warning or fatal error.\n* 2012/09/04 - v0.3.15 - Fixing a minor problem with renaming multi tasks.\n* 2012/08/29 - v0.3.14 - Grunt plugins lacking package.json keywords should work again.\n* 2012/08/27 - v0.3.13 - Fixed Node.js 0.8.x path.existsSync warning. Updated connect, nodeunit, uglify-js deps to latest. Updated docs. Grunt plugins generated with init:gruntplugin no longer include grunt as a dependency. Added preliminary support for \"collection\" plugins.\n* 2012/07/30 - v0.3.12 - Fixing a bug in node 0.8.x where utils.spawn would terminate before receiving all child stdout.\n* 2012/06/25 - v0.3.10 - Updating a few dependencies to work with node 0.8.x (0.6.x should still work).\n* 2012/04/18 - v0.3.9 - The min task (via the uglify helper) now appends a semicolon to the end of the generated source.\n* 2012/04/06 - v0.3.8 - Init template tweaks. Anchor links added to docs, along with grunt-internal docs task to generate them. The watch task now supports multiple targets with separate wildcards and tasks. Locally-installed grunt will override global grunt even when run from global \"grunt\" script.\n* 2012/04/01 - v0.3.7 - Tweaked the behavior of the init template `exports.warnOn` property and added more init template documentation. Fixed duplicate PhantomJS debug output in qunit task. Added useful nodeunit and qunit comments into init template generated test .js files.\n* 2012/03/28 - v0.3.6 - Fixed a `--help` screen issue, a few grunt plugin related issues, and attempted to improve the overall grunt plugin docs and API.\n* 2012/03/27 - v0.3.5 - Fixed a handful of weird Windows issues. Changed default m/d/yyyy dates to yyyy-mm-dd ISO 8601. Fixed some init task bugs, docs errata, and added a lot more content to the init task docs.\n* 2012/03/26 - v0.3.3 - Added a \"gruntfile\" init template. Create a basic gruntfile in seconds with `grunt init:gruntfile`. A few other minor fixes.\n* 2012/03/25 - v0.3.2 - Init tasks can now specify a file matching wildcard for the initial \"files exist\" warning. The jQuery init template now has jQuery 1.7.2. Fixed a bug in the `task.expand*` methods.\n* 2012/03/25 - v0.3.1 - Added a few methods. Substantially reworked the init task and templates.\n* 2012/03/23 - v0.3.0 - Too many changes to list. But in brief: completely reorganized the API, removed all globals, added docs and examples for nearly everything, built a preliminary plugin system (that still needs to be tested). PLEASE RTFM OK? THX U.\n* 2012/02/03 - v0.2.14 - Added a server task (which starts a static webserver for your tasks). The qunit task now uses PhantomJS instead of Zombie.js (4768 of 4971 jQuery unit test pass, neat), and supports both file wildcards as well as http:// or https:// urls. (static webserver, anyone?). Grunt should no longer \"hang\" when done.\n* 2012/01/29 - v0.2.5 - Added a \"qunit\" task as well as an init \"jquery\" template (as of now, there are also \"node\" and \"commonjs\" init templates).\n* 2012/01/22 - v0.2.1 - Removed handlebars, templates are universally handled by underscore now. Changed init task template tags from <% %> to {% %}. Banners beginning with /*! will no longer be stripped.\n* 2012/01/22 - v0.2.0 - Added \"init\" task with a sample template, reworked a lot of code. Hopefully it's backwards-compatible.\n* 2012/01/11 - v0.1.0 - Initial release.\n\n## License\nCopyright (c) 2012 \"Cowboy\" Ben Alman \nLicensed under the MIT license. \n\n\n\n[docs]: /gruntjs/grunt/blob/master/docs/toc.md\n[docs-init]: /gruntjs/grunt/blob/master/docs/task_init.md\n[issues]: /gruntjs/grunt/issues\n\n[node]: http://nodejs.org/\n[npm]: http://npmjs.org/\n[jshint]: http://www.jshint.com/\n[uglify]: https://github.com/mishoo/UglifyJS/\n[nodeunit]: https://github.com/caolan/nodeunit\n[qunit]: http://docs.jquery.com/QUnit\n[phantom]: http://www.phantomjs.org/\n", + "readmeFilename": "README.md", + "_id": "grunt@0.3.17", "_from": "grunt@~0.3.8" } diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/concat.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/concat.js index 579c7c6..edd562e 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/concat.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/concat.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js index 28a9b99..f21684c 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { @@ -452,6 +452,7 @@ module.exports = function(grunt) { if (repo != null) { parts = repo.split('/'); data.git_user = parts[parts.length - 2]; + data.git_repo = parts[parts.length - 1]; done(); } else { // Attempt to pull the data from the user's git config. @@ -461,6 +462,7 @@ module.exports = function(grunt) { fallback: '' }, function(err, result, code) { data.git_user = result || process.env.USER || process.env.USERNAME || '???'; + data.git_repo = path.basename(process.cwd()); done(); }); } @@ -524,7 +526,7 @@ module.exports = function(grunt) { }, jquery_version: { message: 'Required jQuery version', - default: '>= 1.6', + default: '*', warning: 'Must be a valid semantic version range descriptor.' }, node_version: { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs.js index 6752a83..7863dd4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Basic template description. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/README.md b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/README.md index 893e35c..01dfdb2 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/README.md @@ -14,8 +14,8 @@ var {%= js_safe_name %} = require('{%= name %}'); ### In the browser Download the [production version][min] or the [development version][max]. -[min]: https://raw.github.com/{%= git_user %}/{%= name %}/master/dist/{%= name %}.min.js -[max]: https://raw.github.com/{%= git_user %}/{%= name %}/master/dist/{%= name %}.js +[min]: https://raw.github.com/{%= git_user %}/{%= git_repo %}/master/dist/{%= name %}.min.js +[max]: https://raw.github.com/{%= git_user %}/{%= git_repo %}/master/dist/{%= name %}.js In your web page: @@ -45,7 +45,7 @@ _(Coming soon)_ _(Coming soon)_ ## 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](https://github.com/cowboy/grunt). +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/). _Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!_ diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile.js index f1419cf..007b267 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Basic template description. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin.js index 01b771b..b7ec6a4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Basic template description. @@ -12,7 +12,7 @@ exports.description = 'Create a grunt plugin, including Nodeunit unit tests.'; // Template-specific notes to be displayed before question prompts. exports.notes = 'The grunt plugin system is still under development. For ' + - 'more information, see the docs at https://github.com/cowboy/grunt/blob/master/docs/plugins.md'; + 'more information, see the docs at https://github.com/gruntjs/grunt/blob/master/docs/plugins.md'; // Any existing file or directory matching this wildcard will cause a warning. exports.warnOn = '*'; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/README.md b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/README.md index 0f22951..b0aba01 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/README.md @@ -11,8 +11,8 @@ Then add this line to your project's `grunt.js` gruntfile: grunt.loadNpmTasks('{%= full_name %}'); ``` -[grunt]: https://github.com/cowboy/grunt -[getting_started]: https://github.com/cowboy/grunt/blob/master/docs/getting_started.md +[grunt]: http://gruntjs.com/ +[getting_started]: https://github.com/gruntjs/grunt/blob/master/docs/getting_started.md ## Documentation _(Coming soon)_ diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/tasks/name.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/tasks/name.js index d6982c4..9c0f861 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/tasks/name.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/tasks/name.js @@ -9,7 +9,7 @@ module.exports = function(grunt) { // Please see the grunt documentation for more information regarding task and - // helper creation: https://github.com/cowboy/grunt/blob/master/docs/toc.md + // helper creation: https://github.com/gruntjs/grunt/blob/master/docs/toc.md // ========================================================================== // TASKS diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery.js index 02c4f48..410da68 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Basic template description. @@ -17,7 +17,7 @@ exports.notes = '_Project name_ should not contain "jquery" or "js" and ' + 'the word "jQuery", although it may. For example, a plugin titled "Awesome ' + 'jQuery Plugin" might have the name "awesome-plugin". For more information ' + 'please see the documentation at ' + - 'https://github.com/jquery/plugins.jquery.com/blob/master/docs/jquery.json.md'; + 'https://github.com/jquery/plugins.jquery.com/blob/master/docs/manifest.md'; // Any existing file or directory matching this wildcard will cause a warning. exports.warnOn = '*'; @@ -38,7 +38,7 @@ exports.template = function(grunt, init, done) { grunt.helper('prompt_for', 'repository'), grunt.helper('prompt_for', 'homepage'), grunt.helper('prompt_for', 'bugs'), - grunt.helper('prompt_for', 'licenses', 'MIT GPL'), + grunt.helper('prompt_for', 'licenses', 'MIT'), grunt.helper('prompt_for', 'author_name'), grunt.helper('prompt_for', 'author_email'), grunt.helper('prompt_for', 'author_url'), diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/CONTRIBUTING.md b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/CONTRIBUTING.md new file mode 100644 index 0000000..94af472 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# Contributing + +## Important notes +Please don't edit files in the `dist` subdirectory as they are generated via grunt. You'll find source code in the `src` subdirectory! + +### Code style +Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.** + +### PhantomJS +While grunt can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn't be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers. + +See the [Why does grunt complain that PhantomJS isn't installed?](https://github.com/gruntjs/grunt/blob/master/docs/faq.md#why-does-grunt-complain-that-phantomjs-isnt-installed) guide in the [Grunt FAQ](https://github.com/gruntjs/grunt/blob/master/docs/faq.md) for help with installing or troubleshooting PhantomJS. + +## Modifying the code +First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. + +Test that grunt is installed globally by running `grunt --version` at the command-line. If grunt isn't installed globally, run `npm install -g grunt` to install the latest version. _You may need to run `sudo npm install -g grunt`._ + +_Note that in Windows, you may have to run `grunt.cmd` instead of `grunt`._ + +1. Fork and clone the repo. +1. Run `npm install` to install all dependencies (including grunt). +1. Run `grunt` to grunt this project. + +Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing is broken. + +## Submitting pull requests + +1. Create a new branch, please don't work in your `master` branch directly. +1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail. +1. Fix stuff. +1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done. +1. Open `test/*.html` unit test file(s) in actual browser to ensure tests pass everywhere. +1. Update the documentation to reflect any changes. +1. Push to your fork and submit a pull request. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/README.md b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/README.md index c0b15aa..2b5c59a 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/README.md @@ -5,8 +5,8 @@ ## Getting Started Download the [production version][min] or the [development version][max]. -[min]: https://raw.github.com/{%= git_user %}/{%= name %}/master/dist/{%= name %}.min.js -[max]: https://raw.github.com/{%= git_user %}/{%= name %}/master/dist/{%= name %}.js +[min]: https://raw.github.com/{%= git_user %}/{%= git_repo %}/master/dist/{%= name %}.min.js +[max]: https://raw.github.com/{%= git_user %}/{%= git_repo %}/master/dist/{%= name %}.js In your web page: @@ -28,37 +28,3 @@ _(Coming soon)_ ## Release History _(Nothing yet)_ - -## License -Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} -Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. - -## 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](https://github.com/cowboy/grunt). - -### Important notes -Please don't edit files in the `dist` subdirectory as they are generated via grunt. You'll find source code in the `src` subdirectory! - -While grunt can run the included unit tests via PhantomJS, this shouldn't be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers. - -### Installing grunt -_This assumes you have [node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed already._ - -1. Test that grunt is installed globally by running `grunt --version` at the command-line. -1. If grunt isn't installed globally, run `npm install -g grunt` to install the latest version. _You may need to run `sudo npm install -g grunt`._ -1. From the root directory of this project, run `npm install` to install the project's dependencies. - -### Installing PhantomJS - -In order for the qunit task to work properly, [PhantomJS](http://www.phantomjs.org/) must be installed and in the system PATH (if you can run "phantomjs" at the command line, this task should work). - -Unfortunately, PhantomJS cannot be installed automatically via npm or grunt, so you need to install it yourself. There are a number of ways to install PhantomJS. - -* [PhantomJS and Mac OS X](http://ariya.ofilabs.com/2012/02/phantomjs-and-mac-os-x.html) -* [PhantomJS Installation](http://code.google.com/p/phantomjs/wiki/Installation) (PhantomJS wiki) - -Note that the `phantomjs` executable needs to be in the system `PATH` for grunt to see it. - -* [How to set the path and environment variables in Windows](http://www.computerhope.com/issues/ch000549.htm) -* [Where does $PATH get set in OS X 10.6 Snow Leopard?](http://superuser.com/questions/69130/where-does-path-get-set-in-os-x-10-6-snow-leopard) -* [How do I change the PATH variable in Linux](https://www.google.com/search?q=How+do+I+change+the+PATH+variable+in+Linux) diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node.js index d9e47a4..bee75b4 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ // Basic template description. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/README.md b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/README.md index ba83591..bb67667 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/README.md +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/README.md @@ -17,7 +17,7 @@ _(Coming soon)_ _(Coming soon)_ ## 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](https://github.com/cowboy/grunt). +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](https://github.com/gruntjs/grunt). ## Release History _(Nothing yet)_ diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js index 38f67b8..dfbfeb8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js index d9b82fa..536e406 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js index ed060bf..e6265cd 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js index f276dbd..851afd8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { @@ -189,6 +189,8 @@ module.exports = function(grunt) { grunt.helper('phantomjs', { code: 90, args: [ + // PhantomJS options. + '--config=' + grunt.task.getFile('qunit/phantom.json'), // The main script file. grunt.task.getFile('qunit/phantom.js'), // The temporary file used for communications. @@ -196,9 +198,7 @@ module.exports = function(grunt) { // The QUnit helper file to be injected. grunt.task.getFile('qunit/qunit.js'), // URL to the QUnit .html test file to run. - url, - // PhantomJS options. - '--config=' + grunt.task.getFile('qunit/phantom.json') + url ], done: function(err) { if (err) { @@ -244,7 +244,7 @@ module.exports = function(grunt) { ' the command line, this task should work). Unfortunately, ' + 'PhantomJS cannot be installed automatically via npm or grunt. ' + 'See the grunt FAQ for PhantomJS installation instructions: ' + - 'https://github.com/cowboy/grunt/blob/master/docs/faq.md' + 'https://github.com/gruntjs/grunt/blob/master/docs/faq.md' ); grunt.warn('PhantomJS not found.', options.code); } else { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.js index ac2291b..ab4cdc8 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ /*global phantom:true*/ diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/qunit.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/qunit.js index 3796879..f775426 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/qunit.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/qunit.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ /*global QUnit:true, alert:true*/ @@ -20,7 +20,7 @@ function sendMessage() { alert(JSON.stringify(args)); } -QUnit.log = function(obj) { +QUnit.log(function(obj) { // What is this I don’t even if (obj.message === '[object Object], undefined:undefined') { return; } // Parse some stuff before sending it. @@ -28,28 +28,28 @@ QUnit.log = function(obj) { var expected = QUnit.jsDump.parse(obj.expected); // Send it. sendMessage('log', obj.result, actual, expected, obj.message, obj.source); -}; +}); -QUnit.testStart = function(obj) { +QUnit.testStart(function(obj) { sendMessage('testStart', obj.name); -}; +}); -QUnit.testDone = function(obj) { +QUnit.testDone(function(obj) { sendMessage('testDone', obj.name, obj.failed, obj.passed, obj.total); -}; +}); -QUnit.moduleStart = function(obj) { +QUnit.moduleStart(function(obj) { sendMessage('moduleStart', obj.name); -}; +}); -QUnit.moduleDone = function(obj) { +QUnit.moduleDone(function(obj) { sendMessage('moduleDone', obj.name, obj.failed, obj.passed, obj.total); -}; +}); -QUnit.begin = function() { +QUnit.begin(function() { sendMessage('begin'); -}; +}); -QUnit.done = function(obj) { +QUnit.done(function(obj) { sendMessage('done', obj.failed, obj.passed, obj.total, obj.runtime); -}; +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/server.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/server.js index 7a7d391..450e8de 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/server.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/server.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js index c66b129..048665a 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js index f1cd019..98e61b1 100644 --- a/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js @@ -1,10 +1,10 @@ /* * grunt - * https://github.com/cowboy/grunt + * http://gruntjs.com/ * * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. - * http://benalman.com/about/license/ + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT */ module.exports = function(grunt) { diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/lintTest.js b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/lintTest.js new file mode 100644 index 0000000..3b27fb9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/lintTest.js @@ -0,0 +1,10 @@ +var a = 0 + , b = 1 + , c = 2 + , d = 3 + +var foo = function(varA, varB, varC, varD) { + return varA + varB + varC + varD +} + +foo(a, b, c, d) diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/tasks/lint_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/lint_test.js new file mode 100644 index 0000000..66e16cc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/lint_test.js @@ -0,0 +1,28 @@ +var grunt = require('../../lib/grunt'); + +// In case the grunt being used to test is different than the grunt being +// tested, initialize the task and config subsystems. +if (grunt.task.searchDirs.length === 0) { + grunt.task.init([]); + grunt.config.init({}); +} + +// Just tests whether options are correctly set +exports['jshint'] = function(test) { + test.expect(1); + + var options = { + asi: true, + laxcomma: true, + maxparams: 3 + }; + var globals = { + node: true + }; + + var errorcount = grunt.fail.errorcount; + grunt.helper('lint', grunt.file.read('test/fixtures/lintTest.js'), options, globals); + test.equal(grunt.fail.errorcount - errorcount, 1, 'One error should have been logged.'); + + test.done(); +}; diff --git a/node_modules/grunt-coffee/package.json b/node_modules/grunt-coffee/package.json index bebee41..527bf27 100644 --- a/node_modules/grunt-coffee/package.json +++ b/node_modules/grunt-coffee/package.json @@ -73,9 +73,7 @@ "gruntplugin" ], "readme": "[![build status](https://secure.travis-ci.org/avalade/grunt-coffee.png)](http://travis-ci.org/avalade/grunt-coffee)\n# grunt-coffee\n\nJavaScripts your Coffee\n\n## Getting Started\nInstall this grunt plugin next to your project's [grunt.js gruntfile][getting_started] with: `npm install grunt-coffee`\n\nThen add this line to your project's `grunt.js` gruntfile:\n\n```javascript\ngrunt.loadNpmTasks('grunt-coffee');\n```\n\n[grunt]: https://github.com/cowboy/grunt\n[getting_started]: https://github.com/cowboy/grunt/blob/master/docs/getting_started.md\n\n## Documentation\nYou'll need to install `grunt-coffee` first:\n\n npm install grunt-coffee\n\nThen modify your `grunt.js` file by adding the following line:\n\n grunt.loadNpmTasks('grunt-coffee');\n\nThen add some configuration for the plugin like so:\n\n grunt.initConfig({\n ...\n coffee: {\n app: {\n src: ['path/to/coffee/files/*.coffee'],\n dest: 'where/you/want/your/js/files',\n options: {\n bare: true\n }\n }\n },\n ...\n });\n\nThen just run `grunt coffee` and enjoy!\n\nGrunt Coffee will, by default, run coffee with the `--bare` flag set.\nIf you want to run it with the top level variable safety, make sure\nyou set your options to:\n\n options: {\n bare: false\n }\n\nIf you have `dest` path and want to preserve the directory structure of your coffee files, pass the `preserve_dirs` option.\n\n options: {\n preserve_dirs: true\n }\n\nAlso, if you just want to preserve the directory structure, starting from a base path, pass the `base_path` option.\n\n options: {\n preserve_dirs: true,\n base_path: 'path/to'\n }\n\nThis will create the files under `where/you/want/your/js/files/coffee/files/`.\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][grunt].\n\n## Release History\n0.0.6 - addressed when Javascript files are included in the src matcher, thanks [Enleur](https://github.com/Enleur) and [brewster1134](https://github.com/brewster1134)\n\n0.0.5 - added `base_path` option, thanks\n[siriux](https://github.com/siriux) and\n[William](https://github.com/wlepinski).\n\n0.0.4 - added preservation of directory structure, thanks\n[Kevin](https://github.com/rockwood). Also added a unique copy of the\noptions for each call to the helper, thanks [Ken](https://github.com/elfsternberg).\n\n0.0.3 - added relative compilation and compound file suffixes, thanks\n[Pete](https://github.com/petebacondarwin). Also added real error\nmessages, thanks [Tim](https://github.com/timoxley)\n\n0.0.2 - added the options object, thanks\n[Derek](https://github.com/dlindahl)!\n\n0.0.1 - The bare minimum necessary... don't expect it to work\n\n## License\nCopyright (c) 2012 Aaron D. Valade\nLicensed under the MIT license.\n", + "readmeFilename": "README.md", "_id": "grunt-coffee@0.0.6", - "dist": { - "shasum": "abafa73d7fd205844905575e8f8bbd5d6dc78635" - }, "_from": "grunt-coffee" } diff --git a/node_modules/grunt-mocha/HISTORY.md b/node_modules/grunt-mocha/HISTORY.md index fbc1198..c4bb5d7 100644 --- a/node_modules/grunt-mocha/HISTORY.md +++ b/node_modules/grunt-mocha/HISTORY.md @@ -1,3 +1,17 @@ +# 0.1.7 +* Fix bad legacy mocha check for mocha < 1.4.2 (rohni) + +# 0.1.6 +* Add ability to pass mocha config options (grep, etc) via grunt task config. (gamtiq) +* Add option to not include `mocha-spec-helper.js` and auto-inject/run with the `run` config option. Note: Still not required for AMD. This requires an if-statement in your HTML spec to check for PhantomJS environment, it's either that or include the helper. See `example/test2.html`. (gamtiq) + +# 0.1.5 +* Fix total duration when testing multiple html spec files in a single task. (chevalric) + +# 0.1.4 +* **Critical fix:** Compatibility with Mocha 1.4.2 (iammerick) + * If you use `mocha-helper.js` for non-AMD and you want to use Mocha >1.4.2, you replace it with the one in this update. + # 0.1.3 * Remove grunt from deps diff --git a/node_modules/grunt-mocha/README.md b/node_modules/grunt-mocha/README.md index 35d981c..cfef80a 100644 --- a/node_modules/grunt-mocha/README.md +++ b/node_modules/grunt-mocha/README.md @@ -1,18 +1,57 @@ Automatically run *client-side* mocha specs via grunt/mocha/PhantomJS +For a grunt task for server-side mocha tests, see https://github.com/yaymukund/grunt-simple-mocha + # grunt-mocha -(package/README format heavily borrowed from [grunt-jasmine-task](hhttps://github.com/creynders/grunt-jasmine-task) and builtin QUnit task) +(package/README format heavily borrowed from [grunt-jasmine-task](https://github.com/creynders/grunt-jasmine-task) and builtin QUnit task) [Grunt](https://github.com/cowboy/grunt) plugin for running Mocha browser specs in a headless browser (PhantomJS) ## Getting Started -**Important note** +### Task config + +```js +mocha: { + // runs all html files (except test2.html) in the test dir + // In this example, there's only one, but you can add as many as + // you want. You can split them up into different groups here + // ex: admin: [ 'test/admin.html' ] + all: [ 'test/**/!(test2).html' ], + + // Runs 'test/test2.html' with specified mocha options. + // This variant auto-includes 'mocha-helper.js' so you do not have + // to include it in your HTML spec file. Instead, you must add an + // environment check before you run `mocha.run` in your HTML. + test2: { + + // Test files + src: [ 'test/test2.html' ], + + // mocha options + options: { + ignoreLeaks: false, + grep: 'food' + }, + + // Indicates whether 'mocha.run()' should be executed in + // 'mocha-helper.js' + run: true + } +} +``` + +### Vanilla JS + +- Write mocha task description in grunt config using full format and specify `run: true` option (see `example/grunt.js` for details); +- Check for PhantomJS `userAgent` in a test html file and run tests only in a real browser (see `example/test/test2.html` for details). -If you are not using AMD, include `mocha-helper.js` from `tasks/mocha` after you include `mocha.js` and run `mocha.setup`. The helper will override `mocha.setup` if it detects PhantomJS. +In this case you shouldn't include `mocha-helper.js` (it will be included automatically) and tests will be run from `mocha-helper.js`. -See the example folder for a vanilla example. +Alternatively, include `mocha-helper.js` from `tasks/mocha` after you include `mocha.js` and run `mocha.setup` in your HTML file. The helper will override `mocha.setup` if it detects PhantomJS. See `example/test/test.html`. + +### AMD Example setup with AMD (advanced): https://gist.github.com/2655876 @@ -48,12 +87,6 @@ This task is for running Mocha tests in a headless browser, PhantomJS. [See the Use [Mocha](http://visionmedia.github.com/mocha/) -If you are not using AMD, include `mocha-helper.js` from `tasks/mocha` after you include `mocha.js` and run `mocha.setup`. The helper will override `mocha.setup` if it detects PhantomJS. - -See the example folder for a vanilla example. - -Example setup with AMD (advanced): https://gist.github.com/2655876 - ### Maybe Growl? Growl support is optional. I'm not sure what the Windows situation is with growl. diff --git a/node_modules/grunt-mocha/example/grunt.js b/node_modules/grunt-mocha/example/grunt.js index 87aad3e..07f03db 100644 --- a/node_modules/grunt-mocha/example/grunt.js +++ b/node_modules/grunt-mocha/example/grunt.js @@ -21,7 +21,6 @@ module.exports = function(grunt) { 'js/libs/acme/**/*.js' ] }, - // pkg: '', test: { files: ['test/**/*.js'] }, @@ -42,21 +41,43 @@ module.exports = function(grunt) { } }, mocha: { - // runs all html files in the test dir + // runs all html files (except test2.html) in the test dir // In this example, there's only one, but you can add as many as // you want. You can split them up into different groups here // ex: admin: [ 'test/admin.html' ] - all: [ 'test/**/*.html' ], + all: [ 'test/**/!(test2).html' ], + + // Runs 'test/test2.html' with specified mocha options. + // This variant auto-includes 'mocha-helper.js' so you do not have + // to include it in your HTML spec file. Instead, you must add an + // environment check before you run `mocha.run` in your HTML. + test2: { + + // Test files + src: [ 'test/test2.html' ], + + // mocha options + mocha: { + ignoreLeaks: false, + grep: 'food' + }, + + // Indicates whether 'mocha.run()' should be executed in + // 'mocha-helper.js' + run: true + } } }); - - // run `npm install grunt-mocha` in project root dir first - // grunt.loadNpmTasks('grunt-mocha'); - task.loadTasks('../tasks'); + + // @DEBUG Remove this line in your grunt file, this is just for testing + grunt.loadTasks('../tasks'); // Alias 'test' to 'mocha' so you can run `grunt test` task.registerTask('test', 'mocha'); // Default task. task.registerTask('default', 'mocha'); + + // run `npm install grunt-mocha` in project root dir and uncomment this + // grunt.loadNpmTasks('grunt-mocha'); }; diff --git a/node_modules/grunt-mocha/example/test/css/mocha.css b/node_modules/grunt-mocha/example/test/css/mocha.css index 72f181e..8076d0e 100644 --- a/node_modules/grunt-mocha/example/test/css/mocha.css +++ b/node_modules/grunt-mocha/example/test/css/mocha.css @@ -1,4 +1,4 @@ - +@charset "UTF-8"; body { font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; padding: 60px 50px; @@ -143,6 +143,14 @@ body { -webkit-box-shadow: 0 1px 3px #eee; } +#report.pass .test.fail { + display: none; +} + +#report.fail .test.pass { + display: none; +} + #error { color: #c00; font-size: 1.5 em; @@ -168,6 +176,15 @@ body { color: black; } +#stats a { + text-decoration: none; + color: inherit; +} + +#stats a:hover { + border-bottom: 1px solid #eee; +} + #stats li { display: inline-block; margin: 0 5px; diff --git a/node_modules/grunt-mocha/example/test/js/mocha.js b/node_modules/grunt-mocha/example/test/js/mocha.js index fe8dc5d..f67fd02 100644 --- a/node_modules/grunt-mocha/example/test/js/mocha.js +++ b/node_modules/grunt-mocha/example/test/js/mocha.js @@ -433,6 +433,19 @@ Context.prototype.timeout = function(ms){ return this; }; +/** + * Set test slowness threshold `ms`. + * + * @param {Number} ms + * @return {Context} self + * @api private + */ + +Context.prototype.slow = function(ms){ + this.runnable().slow(ms); + return this; +}; + /** * Inspect the context void of `._runnable`. * @@ -535,12 +548,7 @@ var Suite = require('../suite') module.exports = function(suite){ var suites = [suite]; - suite.on('pre-require', function(context){ - - // noop variants - - context.xdescribe = function(){}; - context.xit = function(){}; + suite.on('pre-require', function(context, file, mocha){ /** * Execute before running tests. @@ -585,6 +593,30 @@ module.exports = function(suite){ suites.unshift(suite); fn(); suites.shift(); + return suite; + }; + + /** + * Pending describe. + */ + + context.xdescribe = + context.xcontext = + context.describe.skip = function(title, fn){ + var suite = Suite.create(suites[0], title); + suite.pending = true; + suites.unshift(suite); + fn(); + suites.shift(); + }; + + /** + * Exclusive suite. + */ + + context.describe.only = function(title, fn){ + var suite = context.describe(title, fn); + mocha.grep(suite.fullTitle()); }; /** @@ -594,7 +626,30 @@ module.exports = function(suite){ */ context.it = context.specify = function(title, fn){ - suites[0].addTest(new Test(title, fn)); + var suite = suites[0]; + if (suite.pending) var fn = null; + var test = new Test(title, fn); + suite.addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.it.only = function(title, fn){ + var test = context.it(title, fn); + mocha.grep(test.fullTitle()); + }; + + /** + * Pending test case. + */ + + context.xit = + context.xspecify = + context.it.skip = function(title){ + context.it(title); }; }); }; @@ -805,7 +860,7 @@ var Suite = require('../suite') module.exports = function(suite){ var suites = [suite]; - suite.on('pre-require', function(context){ + suite.on('pre-require', function(context, file, mocha){ /** * Execute before each test case. @@ -850,6 +905,16 @@ module.exports = function(suite){ suites.unshift(suite); fn(); suites.shift(); + return suite; + }; + + /** + * Exclusive test-case. + */ + + context.suite.only = function(title, fn){ + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); }; /** @@ -859,7 +924,18 @@ module.exports = function(suite){ */ context.test = function(title, fn){ - suites[0].addTest(new Test(title, fn)); + var test = new Test(title, fn); + suites[0].addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.test.only = function(title, fn){ + var test = context.test(title, fn); + mocha.grep(test.fullTitle()); }; }); }; @@ -877,7 +953,8 @@ require.register("mocha.js", function(module, exports, require){ * Module dependencies. */ -var path = require('browser/path'); +var path = require('browser/path') + , utils = require('./utils'); /** * Expose `Mocha`. @@ -889,7 +966,7 @@ exports = module.exports = Mocha; * Expose internals. */ -exports.utils = require('./utils'); +exports.utils = utils; exports.interfaces = require('./interfaces'); exports.reporters = require('./reporters'); exports.Runnable = require('./runnable'); @@ -920,6 +997,7 @@ function image(name) { * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` * - `globals` array of accepted globals * - `timeout` timeout in milliseconds + * - `slow` milliseconds to wait before considering a test slow * - `ignoreLeaks` ignore global leaks * - `grep` string or regexp to filter tests with * @@ -935,7 +1013,8 @@ function Mocha(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); + if (options.timeout) this.timeout(options.timeout); + if (options.slow) this.slow(options.slow); } /** @@ -951,16 +1030,24 @@ Mocha.prototype.addFile = function(file){ }; /** - * Set reporter to `name`, defaults to "dot". + * Set reporter to `reporter`, defaults to "dot". * - * @param {String} name + * @param {String|Function} reporter name of a reporter or a reporter constructor * @api public */ -Mocha.prototype.reporter = function(name){ - name = name || 'dot'; - this._reporter = require('./reporters/' + name); - if (!this._reporter) throw new Error('invalid reporter "' + name + '"'); +Mocha.prototype.reporter = function(reporter){ + if ('function' == typeof reporter) { + this._reporter = reporter; + } else { + reporter = reporter || 'dot'; + try { + this._reporter = require('./reporters/' + reporter); + } catch (err) { + this._reporter = require(reporter); + } + if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); + } return this; }; @@ -985,13 +1072,16 @@ Mocha.prototype.ui = function(name){ * @api private */ -Mocha.prototype.loadFiles = function(){ +Mocha.prototype.loadFiles = function(fn){ + var self = this; var suite = this.suite; + var pending = this.files.length; 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); + suite.emit('pre-require', global, file, self); + suite.emit('require', require(file), file, self); + suite.emit('post-require', global, file, self); + --pending || (fn && fn()); }); }; @@ -1001,7 +1091,7 @@ Mocha.prototype.loadFiles = function(){ * @api private */ -Mocha.prototype.growl = function(runner, reporter) { +Mocha.prototype._growl = function(runner, reporter) { var notify = require('growl'); runner.on('end', function(){ @@ -1020,20 +1110,107 @@ Mocha.prototype.growl = function(runner, reporter) { }; /** - * Add regexp to grep for to the options object + * Add regexp to grep, if `re` is a string it is escaped. * - * @param {RegExp} or {String} re + * @param {RegExp|String} re * @return {Mocha} * @api public */ Mocha.prototype.grep = function(re){ this.options.grep = 'string' == typeof re - ? new RegExp(re) + ? new RegExp(utils.escapeRegexp(re)) : re; return this; }; +/** + * Invert `.grep()` matches. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.invert = function(){ + this.options.invert = true; + return this; +}; + +/** + * Ignore global leaks. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.ignoreLeaks = function(){ + this.options.ignoreLeaks = true; + return this; +}; + +/** + * Enable global leak checking. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.checkLeaks = function(){ + this.options.ignoreLeaks = false; + return this; +}; + +/** + * Enable growl support. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.growl = function(){ + this.options.growl = true; + return this; +}; + +/** + * Ignore `globals` array or string. + * + * @param {Array|String} globals + * @return {Mocha} + * @api public + */ + +Mocha.prototype.globals = function(globals){ + this.options.globals = (this.options.globals || []).concat(globals); + return this; +}; + +/** + * Set the timeout in milliseconds. + * + * @param {Number} timeout + * @return {Mocha} + * @api public + */ + +Mocha.prototype.timeout = function(timeout){ + this.suite.timeout(timeout); + return this; +}; + +/** + * Set slowness threshold in milliseconds. + * + * @param {Number} slow + * @return {Mocha} + * @api public + */ + +Mocha.prototype.slow = function(slow){ + this.suite.slow(slow); + return this; +}; + /** * Run tests and invoke `fn()` when complete. * @@ -1043,20 +1220,104 @@ Mocha.prototype.grep = function(re){ */ Mocha.prototype.run = function(fn){ - this.loadFiles(); + if (this.files.length) 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.grep) runner.grep(options.grep, options.invert); if (options.globals) runner.globals(options.globals); - if (options.growl) this.growl(runner, reporter); + if (options.growl) this._growl(runner, reporter); return runner.run(fn); }; }); // module: mocha.js +require.register("ms.js", function(module, exports, require){ + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; + +/** + * Parse or format the given `val`. + * + * @param {String|Number} val + * @return {String|Number} + * @api public + */ + +module.exports = function(val){ + if ('string' == typeof val) return parse(val); + return format(val); +} + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); + if (!m) return; + var n = parseFloat(m[1]); + var type = (m[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * 31557600000; + case 'days': + case 'day': + case 'd': + return n * 86400000; + case 'hours': + case 'hour': + case 'h': + return n * 3600000; + case 'minutes': + case 'minute': + case 'm': + return n * 60000; + case 'seconds': + case 'second': + case 's': + return n * 1000; + case 'ms': + return n; + } +} + +/** + * Format the given `ms`. + * + * @param {Number} ms + * @return {String} + * @api public + */ + +function format(ms) { + if (ms == d) return (ms / d) + ' day'; + if (ms > d) return (ms / d) + ' days'; + if (ms == h) return (ms / h) + ' hour'; + if (ms > h) return (ms / h) + ' hours'; + if (ms == m) return (ms / m) + ' minute'; + if (ms > m) return (ms / m) + ' minutes'; + if (ms == s) return (ms / s) + ' second'; + if (ms > s) return (ms / s) + ' seconds'; + return ms + ' ms'; +} +}); // module: ms.js + require.register("reporters/base.js", function(module, exports, require){ /** @@ -1064,7 +1325,8 @@ require.register("reporters/base.js", function(module, exports, require){ */ var tty = require('browser/tty') - , diff = require('browser/diff'); + , diff = require('browser/diff') + , ms = require('../ms'); /** * Save timer references to avoid Sinon interfering (see GH-237). @@ -1134,7 +1396,7 @@ exports.colors = { var color = exports.color = function(type, str) { if (!exports.useColors) return str; - return '\033[' + exports.colors[type] + 'm' + str + '\033[0m'; + return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; }; /** @@ -1157,19 +1419,19 @@ exports.window = { exports.cursor = { hide: function(){ - process.stdout.write('\033[?25l'); + process.stdout.write('\u001b[?25l'); }, show: function(){ - process.stdout.write('\033[?25h'); + process.stdout.write('\u001b[?25h'); }, deleteLine: function(){ - process.stdout.write('\033[2K'); + process.stdout.write('\u001b[2K'); }, beginningOfLine: function(){ - process.stdout.write('\033[0G'); + process.stdout.write('\u001b[0G'); }, CR: function(){ @@ -1178,13 +1440,6 @@ exports.cursor = { } }; -/** - * A test is considered slow if it - * exceeds the following value in milliseconds. - */ - -exports.slow = 75; - /** * Outut the given `failures` as a list. * @@ -1286,8 +1541,8 @@ function Base(runner) { runner.on('pass', function(test){ stats.passes = stats.passes || 0; - var medium = exports.slow / 2; - test.speed = test.duration > exports.slow + var medium = test.slow() / 2; + test.speed = test.duration > test.slow() ? 'slow' : test.duration > medium ? 'medium' @@ -1350,12 +1605,12 @@ Base.prototype.epilogue = function(){ // pass fmt = color('bright pass', ' ✔') + color('green', ' %d %s complete') - + color('light', ' (%dms)'); + + color('light', ' (%s)'); console.log(fmt, stats.tests || 0, pluralize(stats.tests), - stats.duration); + ms(stats.duration)); // pending if (stats.pending) { @@ -1392,7 +1647,10 @@ function pad(str, len) { 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(''); + str.value = str.value + .replace(/\t/g, '') + .replace(/\r/g, '') + .replace(/\n/g, '\n'); if (str.added) return colorLines('diff added', str.value); if (str.removed) return colorLines('diff removed', str.value); return str.value; @@ -1504,6 +1762,7 @@ function Dot(runner) { var self = this , stats = this.stats , width = Base.window.width * .75 | 0 + , c = '․' , n = 0; runner.on('start', function(){ @@ -1511,21 +1770,21 @@ function Dot(runner) { }); runner.on('pending', function(test){ - process.stdout.write(color('pending', '.')); + process.stdout.write(color('pending', c)); }); runner.on('pass', function(test){ if (++n % width == 0) process.stdout.write('\n '); if ('slow' == test.speed) { - process.stdout.write(color('bright yellow', '.')); + process.stdout.write(color('bright yellow', c)); } else { - process.stdout.write(color(test.speed, '.')); + process.stdout.write(color(test.speed, c)); } }); runner.on('fail', function(test, err){ if (++n % width == 0) process.stdout.write('\n '); - process.stdout.write(color('fail', '.')); + process.stdout.write(color('fail', c)); }); runner.on('end', function(){ @@ -1630,8 +1889,8 @@ exports = module.exports = HTML; var statsTemplate = '
      ' + '
    • ' - + '
    • passes: 0
    • ' - + '
    • failures: 0
    • ' + + '
    • passes: 0
    • ' + + '
    • failures: 0
    • ' + '
    • duration: 0s
    • ' + '
    '; @@ -1642,17 +1901,18 @@ var statsTemplate = '
      ' * @api public */ -function HTML(runner) { +function HTML(runner, root) { 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] + , passesLink = items[1].getElementsByTagName('a')[0] , failures = items[2].getElementsByTagName('em')[0] + , failuresLink = items[2].getElementsByTagName('a')[0] , duration = items[3].getElementsByTagName('em')[0] , canvas = stat.getElementsByTagName('canvas')[0] , report = fragment('
        ') @@ -1660,13 +1920,33 @@ function HTML(runner) { , progress , ctx + root = root || document.getElementById('mocha'); + if (canvas.getContext) { + var ratio = window.devicePixelRatio || 1; + canvas.style.width = canvas.width; + canvas.style.height = canvas.height; + canvas.width *= ratio; + canvas.height *= ratio; ctx = canvas.getContext('2d'); + ctx.scale(ratio, ratio); progress = new Progress; } if (!root) return error('#mocha div missing, add it to your document'); + // pass toggle + on(passesLink, 'click', function () { + var className = /pass/.test(report.className) ? '' : ' pass'; + report.className = report.className.replace(/fail|pass/g, '') + className; + }); + + // failure toggle + on(failuresLink, 'click', function () { + var className = /fail/.test(report.className) ? '' : ' fail'; + report.className = report.className.replace(/fail|pass/g, '') + className; + }); + root.appendChild(stat); root.appendChild(report); @@ -1676,7 +1956,7 @@ function HTML(runner) { if (suite.root) return; // suite - var url = location.protocol + '//' + location.host + location.pathname + '?grep=^' + utils.escapeRegexp(suite.fullTitle()); + var url = '?grep=' + encodeURIComponent(suite.fullTitle()); var el = fragment('
      • %s

      • ', url, escape(suite.title)); // container @@ -1695,6 +1975,8 @@ function HTML(runner) { }); runner.on('test end', function(test){ + window.scrollTo(0, document.body.scrollHeight); + // TODO: add to stats var percent = stats.tests / total * 100 | 0; if (progress) progress.update(percent).draw(ctx); @@ -1732,17 +2014,16 @@ function HTML(runner) { } // 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 h2 = el.getElementsByTagName('h2')[0]; + + on(h2, 'click', function(){ + pre.style.display = 'none' == pre.style.display + ? 'inline-block' + : 'none'; + }); + var pre = fragment('
        %e
        ', utils.clean(test.fn.toString())); el.appendChild(pre); pre.style.display = 'none'; @@ -1802,6 +2083,7 @@ function on(el, event, fn) { el.attachEvent('on' + event, fn); } } + }); // module: reporters/html.js require.register("reporters/index.js", function(module, exports, require){ @@ -1815,13 +2097,15 @@ exports.HTML = require('./html'); exports.List = require('./list'); exports.Min = require('./min'); exports.Spec = require('./spec'); +exports.Nyan = require('./nyan'); +exports.XUnit = require('./xunit'); +exports.Markdown = require('./markdown'); 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') +exports.Teamcity = require('./teamcity'); }); // module: reporters/index.js @@ -2191,14 +2475,14 @@ function Landing(runner) { } // render landing strip - stream.write('\033[4F\n\n'); + stream.write('\u001b[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'); + stream.write('\u001b[0m'); }); runner.on('end', function(){ @@ -2383,6 +2667,7 @@ function Markdown(runner) { }); // module: reporters/markdown.js require.register("reporters/min.js", function(module, exports, require){ + /** * Module dependencies. */ @@ -2407,9 +2692,9 @@ function Min(runner) { runner.on('start', function(){ // clear screen - process.stdout.write('\033[2J'); + process.stdout.write('\u001b[2J'); // set cursor position - process.stdout.write('\033[1;3H'); + process.stdout.write('\u001b[1;3H'); }); runner.on('end', this.epilogue.bind(this)); @@ -2514,7 +2799,7 @@ NyanCat.prototype.drawScoreboard = function(){ function draw(color, n) { write(' '); - write('\033[' + color + 'm' + n + '\033[0m'); + write('\u001b[' + color + 'm' + n + '\u001b[0m'); write('\n'); } @@ -2553,7 +2838,7 @@ NyanCat.prototype.drawRainbow = function(){ var self = this; this.trajectories.forEach(function(line, index) { - write('\033[' + self.scoreboardWidth + 'C'); + write('\u001b[' + self.scoreboardWidth + 'C'); write(line.join('')); write('\n'); }); @@ -2573,7 +2858,7 @@ NyanCat.prototype.drawNyanCat = function(status) { var startWidth = this.scoreboardWidth + this.trajectories[0].length; [0, 1, 2, 3].forEach(function(index) { - write('\033[' + startWidth + 'C'); + write('\u001b[' + startWidth + 'C'); switch (index) { case 0: @@ -2621,7 +2906,7 @@ NyanCat.prototype.drawNyanCat = function(status) { */ NyanCat.prototype.cursorUp = function(n) { - write('\033[' + n + 'A'); + write('\u001b[' + n + 'A'); }; /** @@ -2632,7 +2917,7 @@ NyanCat.prototype.cursorUp = function(n) { */ NyanCat.prototype.cursorDown = function(n) { - write('\033[' + n + 'B'); + write('\u001b[' + n + 'B'); }; /** @@ -2668,7 +2953,7 @@ NyanCat.prototype.generateColors = function(){ NyanCat.prototype.rainbowify = function(str){ var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; this.colorIndex += 1; - return '\033[38;5;' + color + 'm' + str + '\033[0m'; + return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; }; /** @@ -2752,7 +3037,7 @@ function Progress(runner, options) { , i = width - n; cursor.CR(); - process.stdout.write('\033[J'); + process.stdout.write('\u001b[J'); process.stdout.write(color('progress', ' ' + options.open)); process.stdout.write(Array(n).join(options.complete)); process.stdout.write(Array(i).join(options.incomplete)); @@ -2902,10 +3187,10 @@ function TAP(runner) { var self = this , stats = this.stats - , total = runner.total , n = 1; runner.on('start', function(){ + var total = runner.grepTotal(runner.suite); console.log('%d..%d', 1, total); }); @@ -3049,7 +3334,11 @@ function XUnit(runner) { , tests = [] , self = this; - runner.on('test end', function(test){ + runner.on('pass', function(test){ + tests.push(test); + }); + + runner.on('fail', function(test){ tests.push(test); }); @@ -3134,7 +3423,7 @@ require.register("runnable.js", function(module, exports, require){ */ var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('runnable'); + , debug = require('browser/debug')('mocha:runnable'); /** * Save timer references to avoid Sinon interfering (see GH-237). @@ -3166,6 +3455,7 @@ function Runnable(title, fn) { this.async = fn && fn.length; this.sync = ! this.async; this._timeout = 2000; + this._slow = 75; this.timedOut = false; } @@ -3193,6 +3483,21 @@ Runnable.prototype.timeout = function(ms){ return this; }; +/** + * Set & get slow `ms`. + * + * @param {Number} ms + * @return {Runnable|Number} ms or self + * @api private + */ + +Runnable.prototype.slow = function(ms){ + if (0 === arguments.length) return this._slow; + debug('timeout %d', ms); + this._slow = ms; + return this; +}; + /** * Return the full title generated by recursively * concatenating the parent's full title. @@ -3330,7 +3635,7 @@ require.register("runner.js", function(module, exports, require){ */ var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('runner') + , debug = require('browser/debug')('mocha:runner') , Test = require('./test') , utils = require('./utils') , filter = utils.filter @@ -3447,8 +3752,16 @@ Runner.prototype.globals = function(arr){ Runner.prototype.checkGlobals = function(test){ if (this.ignoreLeaks) return; - var leaks = filterLeaks(this._globals); + var ok = this._globals; + var globals = keys(global); + var isNode = process.kill; + var leaks; + + // check length - 2 ('errno' and 'location' globals) + if (isNode && 1 == ok.length - globals.length) return + else if (2 == ok.length - globals.length) return; + leaks = filterLeaks(ok, globals); this._globals = this._globals.concat(leaks); if (leaks.length > 1) { @@ -3504,7 +3817,6 @@ Runner.prototype.failHook = function(hook, err){ Runner.prototype.hook = function(name, fn){ var suite = this.suite , hooks = suite['_' + name] - , ms = suite._timeout , self = this , timer; @@ -3739,9 +4051,9 @@ Runner.prototype.runSuite = function(suite, fn){ */ Runner.prototype.uncaught = function(err){ - debug('uncaught exception'); + debug('uncaught exception %s', err.message); var runnable = this.currentRunnable; - if ('failed' == runnable.state) return; + if (!runnable || 'failed' == runnable.state) return; runnable.clearTimeout(); err.uncaught = true; this.fail(runnable, err); @@ -3801,12 +4113,13 @@ Runner.prototype.run = function(fn){ * Filter leaks with the given globals flagged as `ok`. * * @param {Array} ok + * @param {Array} globals * @return {Array} * @api private */ -function filterLeaks(ok) { - return filter(keys(global), function(key){ +function filterLeaks(ok, globals) { + return filter(globals, function(key){ var matched = filter(ok, function(ok){ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); return key == ok; @@ -3814,6 +4127,7 @@ function filterLeaks(ok) { return matched.length == 0 && (!global.navigator || 'onerror' !== key); }); } + }); // module: runner.js require.register("suite.js", function(module, exports, require){ @@ -3823,7 +4137,8 @@ require.register("suite.js", function(module, exports, require){ */ var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('suite') + , debug = require('browser/debug')('mocha:suite') + , milliseconds = require('./ms') , utils = require('./utils') , Hook = require('./hook'); @@ -3849,6 +4164,7 @@ exports = module.exports = Suite; exports.create = function(parent, title){ var suite = new Suite(title, parent.ctx); suite.parent = parent; + if (parent.pending) suite.pending = true; title = suite.fullTitle(); parent.addSuite(suite); return suite; @@ -3868,12 +4184,14 @@ function Suite(title, ctx) { this.ctx = ctx; this.suites = []; this.tests = []; + this.pending = false; this._beforeEach = []; this._beforeAll = []; this._afterEach = []; this._afterAll = []; this.root = !title; this._timeout = 2000; + this._slow = 75; this._bail = false; } @@ -3897,6 +4215,7 @@ Suite.prototype.clone = function(){ debug('clone'); suite.ctx = this.ctx; suite.timeout(this.timeout()); + suite.slow(this.slow()); suite.bail(this.bail()); return suite; }; @@ -3911,12 +4230,28 @@ Suite.prototype.clone = function(){ Suite.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; - if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000; + if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = parseInt(ms, 10); return this; }; +/** + * Set slow `ms` or short-hand such as "2s". + * + * @param {Number|String} ms + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.slow = function(ms){ + if (0 === arguments.length) return this._slow; + if ('string' == typeof ms) ms = milliseconds(ms); + debug('slow %d', ms); + this._slow = ms; + return this; +}; + /** * Sets whether to bail after first error. * @@ -3941,9 +4276,11 @@ Suite.prototype.bail = function(bail){ */ Suite.prototype.beforeAll = function(fn){ + if (this.pending) return this; var hook = new Hook('"before all" hook', fn); hook.parent = this; hook.timeout(this.timeout()); + hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeAll.push(hook); this.emit('beforeAll', hook); @@ -3959,9 +4296,11 @@ Suite.prototype.beforeAll = function(fn){ */ Suite.prototype.afterAll = function(fn){ + if (this.pending) return this; var hook = new Hook('"after all" hook', fn); hook.parent = this; hook.timeout(this.timeout()); + hook.slow(this.slow()); hook.ctx = this.ctx; this._afterAll.push(hook); this.emit('afterAll', hook); @@ -3977,9 +4316,11 @@ Suite.prototype.afterAll = function(fn){ */ Suite.prototype.beforeEach = function(fn){ + if (this.pending) return this; var hook = new Hook('"before each" hook', fn); hook.parent = this; hook.timeout(this.timeout()); + hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeEach.push(hook); this.emit('beforeEach', hook); @@ -3995,9 +4336,11 @@ Suite.prototype.beforeEach = function(fn){ */ Suite.prototype.afterEach = function(fn){ + if (this.pending) return this; var hook = new Hook('"after each" hook', fn); hook.parent = this; hook.timeout(this.timeout()); + hook.slow(this.slow()); hook.ctx = this.ctx; this._afterEach.push(hook); this.emit('afterEach', hook); @@ -4015,6 +4358,7 @@ Suite.prototype.afterEach = function(fn){ Suite.prototype.addSuite = function(suite){ suite.parent = this; suite.timeout(this.timeout()); + suite.slow(this.slow()); suite.bail(this.bail()); this.suites.push(suite); this.emit('suite', suite); @@ -4032,6 +4376,7 @@ Suite.prototype.addSuite = function(suite){ Suite.prototype.addTest = function(test){ test.parent = this; test.timeout(this.timeout()); + test.slow(this.slow()); test.ctx = this.ctx; this.tests.push(test); this.emit('test', test); @@ -4134,7 +4479,7 @@ require.register("utils.js", function(module, exports, require){ var fs = require('browser/fs') , path = require('browser/path') , join = path.join - , debug = require('browser/debug')('watch'); + , debug = require('browser/debug')('mocha:watch'); /** * Ignored directories. @@ -4150,7 +4495,7 @@ var ignore = ['node_modules', '.git']; * @api private */ -exports.escape = function(html) { +exports.escape = function(html){ return String(html) .replace(/&/g, '&') .replace(/"/g, '"') @@ -4167,7 +4512,7 @@ exports.escape = function(html) { * @api private */ -exports.forEach = function(arr, fn, scope) { +exports.forEach = function(arr, fn, scope){ for (var i = 0, l = arr.length; i < l; i++) fn.call(scope, arr[i], i); }; @@ -4181,7 +4526,7 @@ exports.forEach = function(arr, fn, scope) { * @api private */ -exports.indexOf = function (arr, obj, start) { +exports.indexOf = function(arr, obj, start){ for (var i = start || 0, l = arr.length; i < l; i++) { if (arr[i] === obj) return i; @@ -4195,15 +4540,14 @@ exports.indexOf = function (arr, obj, start) { * @param {Array} array * @param {Function} fn * @param {Object} initial value - * @param {Object} scope * @api private */ -exports.reduce = function(arr, fn, val, scope) { +exports.reduce = function(arr, fn, val){ var rval = val; for (var i = 0, l = arr.length; i < l; i++) { - rval = fn.call(scope, rval, arr[i], i, arr); + rval = fn(rval, arr[i], i, arr); } return rval; @@ -4214,17 +4558,15 @@ exports.reduce = function(arr, fn, val, scope) { * * @param {Array} array * @param {Function} fn - * @param {Object} scope * @api private */ -exports.filter = function(arr, fn, scope) { +exports.filter = function(arr, fn){ 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); + if (fn(val, i, arr)) ret.push(val); } return ret; @@ -4332,7 +4674,7 @@ exports.clean = function(str) { str = str.replace(re, ''); - return str.trim(); + return exports.trim(str); }; /** @@ -4346,6 +4688,72 @@ exports.clean = function(str) { exports.escapeRegexp = function(str){ return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); }; + +/** + * Trim the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.trim = function(str){ + return str.replace(/^\s+|\s+$/g, ''); +}; + +/** + * Parse the given `qs`. + * + * @param {String} qs + * @return {Object} + * @api private + */ + +exports.parseQuery = function(qs){ + return exports.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; + }, {}); +}; + +/** + * Highlight the given string of `js`. + * + * @param {String} js + * @return {String} + * @api private + */ + +function highlight(js) { + return js + .replace(//g, '>') + .replace(/\/\/(.*)/gm, '//$1') + .replace(/('.*?')/gm, '$1') + .replace(/(\d+\.\d+)/gm, '$1') + .replace(/(\d+)/gm, '$1') + .replace(/\bnew *(\w+)/gm, 'new $1') + .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') +} + +/** + * Highlight the contents of tag `name`. + * + * @param {String} name + * @api private + */ + +exports.highlightTags = function(name) { + var code = document.getElementsByTagName(name); + for (var i = 0, len = code.length; i < len; ++i) { + code[i].innerHTML = highlight(code[i].innerHTML); + } +}; + }); // module: utils.js /** * Node shims. @@ -4409,74 +4817,35 @@ process.on = function(e, fn){ } }; -/** - * Expose mocha. - */ - -window.mocha = require('mocha'); - // boot ;(function(){ - var utils = mocha.utils - , options = {} - - mocha.suite = new mocha.Suite('', new mocha.Context()); - - /** - * Highlight the given string of `js`. - */ - - function highlight(js) { - return js - .replace(//g, '>') - .replace(/\/\/(.*)/gm, '//$1') - .replace(/('.*?')/gm, '$1') - .replace(/(\d+\.\d+)/gm, '$1') - .replace(/(\d+)/gm, '$1') - .replace(/\bnew *(\w+)/gm, 'new $1') - .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') - } /** - * Highlight code contents. + * Expose mocha. */ - function highlightCode() { - var code = document.getElementsByTagName('code'); - for (var i = 0, len = code.length; i < len; ++i) { - code[i].innerHTML = highlight(code[i].innerHTML); - } - } + var Mocha = window.Mocha = require('mocha'), + mocha = window.mocha = new Mocha({ reporter: 'html' }); /** - * Parse the given `qs`. + * Override ui to ensure that the ui functions are initialized. + * Normally this would happen in Mocha.prototype.loadFiles. */ - 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; - }, {}); - } + mocha.ui = function(ui){ + Mocha.prototype.ui.call(this, ui); + this.suite.emit('pre-require', window, null, this); + return this; + }; /** * 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) mocha.suite.timeout(options.timeout); - ui(mocha.suite); - mocha.suite.emit('pre-require', window); + if ('string' == typeof opts) opts = { ui: opts }; + for (var opt in opts) this[opt](opts[opt]); + return this; }; /** @@ -4484,17 +4853,16 @@ window.mocha = require('mocha'); */ mocha.run = function(fn){ - mocha.suite.emit('run'); - var runner = new mocha.Runner(mocha.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); + var options = mocha.options; + mocha.globals('location'); + + var query = Mocha.utils.parseQuery(window.location.search || ''); + if (query.grep) mocha.grep(query.grep); + + return Mocha.prototype.run.call(mocha, function(){ + Mocha.utils.highlightTags('code'); + if (fn) fn(); + }); }; })(); })(); \ No newline at end of file diff --git a/node_modules/grunt-mocha/example/test/test2.html b/node_modules/grunt-mocha/example/test/test2.html new file mode 100644 index 0000000..4a12c79 --- /dev/null +++ b/node_modules/grunt-mocha/example/test/test2.html @@ -0,0 +1,44 @@ + + + + + Example Mocha Test + + + + +
        + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/growl/History.md b/node_modules/grunt-mocha/node_modules/growl/History.md index ffa3b19..a4b7b49 100644 --- a/node_modules/grunt-mocha/node_modules/growl/History.md +++ b/node_modules/grunt-mocha/node_modules/growl/History.md @@ -1,4 +1,19 @@ +1.7.0 / 2012-12-30 +================== + + * support transient notifications in Gnome + +1.6.1 / 2012-09-25 +================== + + * restore compatibility with node < 0.8 [fgnass] + +1.6.0 / 2012-09-06 +================== + + * add notification center support [drudge] + 1.5.1 / 2012-04-08 ================== diff --git a/node_modules/grunt-mocha/node_modules/growl/Readme.md b/node_modules/grunt-mocha/node_modules/growl/Readme.md index c40ecab..48d717c 100644 --- a/node_modules/grunt-mocha/node_modules/growl/Readme.md +++ b/node_modules/grunt-mocha/node_modules/growl/Readme.md @@ -1,11 +1,17 @@ # Growl for nodejs -Growl support for Nodejs. This is essentially a port of my [Ruby Growl Library](http://github.com/visionmedia/growl). Ubuntu/Linux support added thanks to [@niftylettuce](http://github.com/niftylettuce). You'll need [growlnotify(1)](http://growl.info/extras.php#growlnotify). +Growl support for Nodejs. This is essentially a port of my [Ruby Growl Library](http://github.com/visionmedia/growl). Ubuntu/Linux support added thanks to [@niftylettuce](http://github.com/niftylettuce). ## Installation +### Install + ### Mac OS X (Darwin): + Install [growlnotify(1)](http://growl.info/extras.php#growlnotify). On OS X 10.8, Notification Center is supported using [terminal-notifier](https://github.com/alloy/terminal-notifier). To install: + + $ sudo gem install terminal-notifier + Install [npm](http://npmjs.org/) and run: $ npm install growl diff --git a/node_modules/grunt-mocha/node_modules/growl/lib/growl.js b/node_modules/grunt-mocha/node_modules/growl/lib/growl.js index 58c6e1c..04f4f9b 100644 --- a/node_modules/grunt-mocha/node_modules/growl/lib/growl.js +++ b/node_modules/grunt-mocha/node_modules/growl/lib/growl.js @@ -5,33 +5,60 @@ */ var exec = require('child_process').exec + , fs = require('fs') , path = require('path') + , exists = fs.existsSync || path.existsSync , os = require('os') + , quote = JSON.stringify , cmd; +function which(name) { + var paths = process.env.PATH.split(':'); + var loc; + + for (var i = 0, len = paths.length; i < len; ++i) { + loc = path.join(paths[i], name); + if (exists(loc)) return loc; + } +} + switch(os.type()) { case 'Darwin': - cmd = { - type: "Darwin" - , pkg: "growlnotify" - , msg: '-m' - , sticky: '--sticky' - , priority: { - cmd: '--priority' - , range: [ - -2 - , -1 - , 0 - , 1 - , 2 - , "Very Low" - , "Moderate" - , "Normal" - , "High" - , "Emergency" - ] - } - }; + if (which('terminal-notifier')) { + cmd = { + type: "Darwin-NotificationCenter" + , pkg: "terminal-notifier" + , msg: '-message' + , title: '-title' + , subtitle: '-subtitle' + , priority: { + cmd: '-execute' + , range: [] + } + }; + } else { + cmd = { + type: "Darwin-Growl" + , pkg: "growlnotify" + , msg: '-m' + , sticky: '--sticky' + , priority: { + cmd: '--priority' + , range: [ + -2 + , -1 + , 0 + , 1 + , 2 + , "Very Low" + , "Moderate" + , "Normal" + , "High" + , "Emergency" + ] + } + }; + } break; case 'Linux': cmd = { @@ -127,7 +154,7 @@ function growl(msg, options, fn) { // image if (image = options.image) { switch(cmd.type) { - case 'Darwin': + case 'Darwin-Growl': var flag, ext = path.extname(image).substr(1) flag = flag || ext == 'icns' && 'iconpath' flag = flag || /^[A-Z]/.test(image) && 'appIcon' @@ -138,9 +165,11 @@ function growl(msg, options, fn) { break; case 'Linux': args.push(cmd.icon + " " + image); + // libnotify defaults to sticky, set a hint for transient notifications + if (!options.sticky) args.push('--hint=int:transient:1'); break; case 'Windows': - args.push(cmd.icon + '"' + image.replace(/\\/g, "\\\\") + '"'); + args.push(cmd.icon + quote(image)); break; } } @@ -158,28 +187,45 @@ function growl(msg, options, fn) { } // name - if (options.name && cmd.type === "Darwin") { + if (options.name && cmd.type === "Darwin-Growl") { args.push('--name', options.name); } switch(cmd.type) { - case 'Darwin': + case 'Darwin-Growl': + args.push(cmd.msg); + args.push(quote(msg)); + if (options.title) args.push(quote(options.title)); + break; + case 'Darwin-NotificationCenter': + args.push(cmd.msg); + args.push(quote(msg)); + if (options.title) { + args.push(cmd.title); + args.push(quote(options.title)); + } + if (options.subtitle) { + args.push(cmd.subtitle); + args.push(quote(options.title)); + } + break; + case 'Darwin-Growl': args.push(cmd.msg); - args.push('"' + msg + '"'); - if (options.title) args.push(options.title); + args.push(quote(msg)); + if (options.title) args.push(quote(options.title)); break; case 'Linux': if (options.title) { - args.push("'" + options.title + "'"); + args.push(quote(options.title)); args.push(cmd.msg); - args.push("'" + msg + "'"); + args.push(quote(msg)); } else { - args.push("'" + msg + "'"); + args.push(quote(msg)); } break; case 'Windows': - args.push('"' + msg + '"'); - if (options.title) args.push(cmd.title + '"' + options.title + '"'); + args.push(quote(msg)); + if (options.title) args.push(cmd.title + quote(options.title)); break; } diff --git a/node_modules/grunt-mocha/node_modules/growl/package.json b/node_modules/grunt-mocha/node_modules/growl/package.json index 277c8e9..caf06b7 100644 --- a/node_modules/grunt-mocha/node_modules/growl/package.json +++ b/node_modules/grunt-mocha/node_modules/growl/package.json @@ -1,13 +1,14 @@ { "name": "growl", - "version": "1.5.1", + "version": "1.7.0", "description": "Growl unobtrusive notifications", "author": { "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" }, "main": "./lib/growl.js", - "readme": "# Growl for nodejs\n\nGrowl support for Nodejs. This is essentially a port of my [Ruby Growl Library](http://github.com/visionmedia/growl). Ubuntu/Linux support added thanks to [@niftylettuce](http://github.com/niftylettuce). You'll need [growlnotify(1)](http://growl.info/extras.php#growlnotify).\n\n## Installation\n\n### Mac OS X (Darwin):\n\n Install [npm](http://npmjs.org/) and run:\n \n $ npm install growl\n\n### Ubuntu (Linux):\n\n Install `notify-send` through the [libnotify-bin](http://packages.ubuntu.com/libnotify-bin) package:\n\n $ sudo apt-get install libnotify-bin\n\n Install [npm](http://npmjs.org/) and run:\n \n $ npm install growl\n\n### Windows:\n\n Download and install [Growl for Windows](http://www.growlforwindows.com/gfw/default.aspx)\n\n Download [growlnotify](http://www.growlforwindows.com/gfw/help/growlnotify.aspx) - **IMPORTANT :** Unpack growlnotify to a folder that is present in your path!\n\n Install [npm](http://npmjs.org/) and run:\n \n $ npm install growl\n\n## Examples\n\nCallback functions are optional\n\n var growl = require('growl')\n growl('You have mail!')\n growl('5 new messages', { sticky: true })\n growl('5 new emails', { title: 'Email Client', image: 'Safari', sticky: true })\n growl('Message with title', { title: 'Title'})\n growl('Set priority', { priority: 2 })\n growl('Show Safari icon', { image: 'Safari' })\n growl('Show icon', { image: 'path/to/icon.icns' })\n growl('Show image', { image: 'path/to/my.image.png' })\n growl('Show png filesystem icon', { image: 'png' })\n growl('Show pdf filesystem icon', { image: 'article.pdf' })\n growl('Show pdf filesystem icon', { image: 'article.pdf' }, function(err){\n // ... notified\n })\n\n## Options\n\n - title\n - notification title\n - name\n - application name\n - priority\n - priority for the notification (default is 0)\n - sticky\n - weither or not the notification should remainin until closed\n - image\n - Auto-detects the context:\n - path to an icon sets --iconpath\n - path to an image sets --image\n - capitalized word sets --appIcon\n - filename uses extname as --icon\n - otherwise treated as --icon\n \n## License \n\n(The MIT License)\n\nCopyright (c) 2009 TJ Holowaychuk \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", - "_id": "growl@1.5.1", + "readme": "# Growl for nodejs\n\nGrowl support for Nodejs. This is essentially a port of my [Ruby Growl Library](http://github.com/visionmedia/growl). Ubuntu/Linux support added thanks to [@niftylettuce](http://github.com/niftylettuce). \n\n## Installation\n\n### Install \n\n### Mac OS X (Darwin):\n\n Install [growlnotify(1)](http://growl.info/extras.php#growlnotify). On OS X 10.8, Notification Center is supported using [terminal-notifier](https://github.com/alloy/terminal-notifier). To install:\n \n $ sudo gem install terminal-notifier\n \n Install [npm](http://npmjs.org/) and run:\n \n $ npm install growl\n\n### Ubuntu (Linux):\n\n Install `notify-send` through the [libnotify-bin](http://packages.ubuntu.com/libnotify-bin) package:\n\n $ sudo apt-get install libnotify-bin\n\n Install [npm](http://npmjs.org/) and run:\n \n $ npm install growl\n\n### Windows:\n\n Download and install [Growl for Windows](http://www.growlforwindows.com/gfw/default.aspx)\n\n Download [growlnotify](http://www.growlforwindows.com/gfw/help/growlnotify.aspx) - **IMPORTANT :** Unpack growlnotify to a folder that is present in your path!\n\n Install [npm](http://npmjs.org/) and run:\n \n $ npm install growl\n\n## Examples\n\nCallback functions are optional\n\n var growl = require('growl')\n growl('You have mail!')\n growl('5 new messages', { sticky: true })\n growl('5 new emails', { title: 'Email Client', image: 'Safari', sticky: true })\n growl('Message with title', { title: 'Title'})\n growl('Set priority', { priority: 2 })\n growl('Show Safari icon', { image: 'Safari' })\n growl('Show icon', { image: 'path/to/icon.icns' })\n growl('Show image', { image: 'path/to/my.image.png' })\n growl('Show png filesystem icon', { image: 'png' })\n growl('Show pdf filesystem icon', { image: 'article.pdf' })\n growl('Show pdf filesystem icon', { image: 'article.pdf' }, function(err){\n // ... notified\n })\n\n## Options\n\n - title\n - notification title\n - name\n - application name\n - priority\n - priority for the notification (default is 0)\n - sticky\n - weither or not the notification should remainin until closed\n - image\n - Auto-detects the context:\n - path to an icon sets --iconpath\n - path to an image sets --image\n - capitalized word sets --appIcon\n - filename uses extname as --icon\n - otherwise treated as --icon\n \n## License \n\n(The MIT License)\n\nCopyright (c) 2009 TJ Holowaychuk \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", + "_id": "growl@1.7.0", "_from": "growl@~1" } diff --git a/node_modules/grunt-mocha/node_modules/growl/test.js b/node_modules/grunt-mocha/node_modules/growl/test.js index 2e75000..cf22d90 100644 --- a/node_modules/grunt-mocha/node_modules/growl/test.js +++ b/node_modules/grunt-mocha/node_modules/growl/test.js @@ -14,3 +14,7 @@ growl('Show pdf filesystem icon', { image: 'article.pdf' }) growl('Show pdf filesystem icon', { image: 'article.pdf' }, function(){ console.log('callback'); }) +growl('Show pdf filesystem icon', { title: 'Use show()', image: 'article.pdf' }) +growl('here \' are \n some \\ characters that " need escaping', {}, function(error, stdout, stderr) { + if (error !== null) throw new Error('escaping failed:\n' + stdout + stderr); +}) diff --git a/node_modules/grunt-mocha/node_modules/temporary/History.md b/node_modules/grunt-mocha/node_modules/temporary/History.md new file mode 100644 index 0000000..2ad4405 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/History.md @@ -0,0 +1,5 @@ + +0.0.5 / 2012-11-12 +================== + + * Solved process.env issue in detector on certain version so linux. diff --git a/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js b/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js index 045cd81..c09b46d 100644 --- a/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js +++ b/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js @@ -19,14 +19,26 @@ */ var detector = module.exports; +var normalize = function(path) { + var last = Array.prototype.pop.apply(path); + + if (process.platform !== "win32" && last !== '/') { + path += '/'; + } + + return path; +} + /** * Returns tmp dir. Thank you npm. * * @returns {String} tmp dir. */ detector.tmp = function() { - return process.env.TMPDIR + var temp = process.env.TMPDIR || process.env.TMP || process.env.TEMP || (process.platform === "win32" ? "c:\\windows\\temp\\" : "/tmp/") + + return normalize(temp); }; \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/package.json b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/package.json index 48d5e4e..3df7344 100644 --- a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/package.json +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/package.json @@ -26,6 +26,7 @@ "node": ">= 0.6.0" }, "readme": "[![Build Status](https://secure.travis-ci.org/vesln/package.png)](http://travis-ci.org/vesln/package)\n\n# package - Easy package.json exports.\n\n## Intro\n\nThis module provides an easy and simple way to export package.json data.\n\n## Installation\n\n\t$ npm install package\n\n## Usage\n\n\tvar package = require('package')(module); // contains package.json data.\n\tvar yourAwesomeModule = {};\n\tyourAwesomeModule.version = package.version;\n\n## Tests\n\n\t$ make test\n\n## Contribution\n\nBug fixes and features are welcomed.\n\n## Other similar modules\n\n- pkginfo (https://github.com/indexzero/node-pkginfo) by indexzero.\n- JSON.parse + fs.readFile\n\n## License\n\nMIT License\n\nCopyright (C) 2012 Veselin Todorov\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\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject 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,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.", + "readmeFilename": "Readme.md", "_id": "package@1.0.1", "_from": "package@>= 1.0.0 < 1.2.0" } diff --git a/node_modules/grunt-mocha/node_modules/temporary/package.json b/node_modules/grunt-mocha/node_modules/temporary/package.json index 1a7d301..0b67aae 100644 --- a/node_modules/grunt-mocha/node_modules/temporary/package.json +++ b/node_modules/grunt-mocha/node_modules/temporary/package.json @@ -1,6 +1,6 @@ { "name": "temporary", - "version": "0.0.4", + "version": "0.0.5", "description": "The lord of tmp.", "keywords": [ "tmp", @@ -33,6 +33,7 @@ "node": ">= 0.6.0" }, "readme": "[![Build Status](https://secure.travis-ci.org/vesln/temporary.png)](http://travis-ci.org/vesln/temporary)\n\n# temporary - The lord of tmp.\n\n## Intro\n\nTemporary provides an easy way to create temporary files and directories.\nIt will create a temporary file/directory with a unique name.\n\n## Features\n\n- Generates unique name.\n- Auto-discovers tmp dir.\n\n## Installation\n\n\t$ npm install temporary\n\n## Usage\n\n\tvar Tempfile = require('temporary/file');\n\tvar Tempdir = require('temporary/dir');\n\tvar file = new Tempfile;\n\tvar dir = new Tempdir;\n\t\n\tconsole.log(file.path); // path.\n\tconsole.log(dir.path); // path.\n\t\n\tfile.unlink();\n\tdir.rmdir();\n\n## Methods\n\n### File\n\n- File.readFile\n- File.readFileSync\n- File.writeFile\n- File.writeFileSync\n- File.open\n- File.openSync\n- File.close\n- File.closeSync\n- File.unlink\n- File.unlinkSync\n\n### Dir\n\n- Dir.rmdir\n- Dir.rmdirSync\n\n## Tests\n\n\t$ make test\n\n## Contribution\n\nBug fixes and features are welcomed.\n\n## License\n\nMIT License\n\nCopyright (C) 2012 Veselin Todorov\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\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject 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,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.", - "_id": "temporary@0.0.4", + "readmeFilename": "Readme.md", + "_id": "temporary@0.0.5", "_from": "temporary@~0.0.2" } diff --git a/node_modules/grunt-mocha/package.json b/node_modules/grunt-mocha/package.json index 310061f..0958781 100644 --- a/node_modules/grunt-mocha/package.json +++ b/node_modules/grunt-mocha/package.json @@ -1,7 +1,7 @@ { "name": "grunt-mocha", "description": "Grunt task for running Mocha specs", - "version": "0.1.3", + "version": "0.1.7", "homepage": "https://github.com/kmiyashiro/grunt-mocha", "author": { "name": "Kelly Miyashiro", @@ -25,9 +25,6 @@ "engines": { "node": "*" }, - "scripts": { - "test": "grunt test" - }, "dependencies": { "temporary": "~0.0.2", "growl": "~1" @@ -41,10 +38,8 @@ "keywords": [ "gruntplugin" ], - "readme": "Automatically run *client-side* mocha specs via grunt/mocha/PhantomJS\n\n# grunt-mocha\n\n(package/README format heavily borrowed from [grunt-jasmine-task](hhttps://github.com/creynders/grunt-jasmine-task) and builtin QUnit task)\n\n[Grunt](https://github.com/cowboy/grunt) plugin for running Mocha browser specs in a headless browser (PhantomJS)\n\n## Getting Started\n\n**Important note**\n\nIf you are not using AMD, include `mocha-helper.js` from `tasks/mocha` after you include `mocha.js` and run `mocha.setup`. The helper will override `mocha.setup` if it detects PhantomJS.\n\nSee the example folder for a vanilla example.\n\nExample setup with AMD (advanced): https://gist.github.com/2655876\n\n### Grunt and this plugin\n\nFirst, make sure you have grunt installed globally, `npm install grunt -g`\n\nInstall this grunt plugin next to your project's [grunt.js gruntfile](https://github.com/cowboy/grunt/blob/master/docs/getting_started.md) with: `npm install grunt-mocha`\n\nThen add this line to your project's `grunt.js` gruntfile at the bottom:\n\n```javascript\ngrunt.loadNpmTasks('grunt-mocha');\n```\n\nAlso add this to the ```grunt.initConfig``` object in the same file:\n\n```javascript\nmocha: {\n index: ['specs/index.html']\n},\n```\n\nReplace ```specs/index.html``` with the location of your mocha spec running html file.\n\nNow you can run the mocha task with `grunt mocha`, but it won't work. That's because you need...\n\n### PhantomJS\n\nThis task is for running Mocha tests in a headless browser, PhantomJS. [See the FAQ on how to install PhantomJS](https://github.com/cowboy/grunt/blob/master/docs/faq.md#why-does-grunt-complain-that-phantomjs-isnt-installed).\n\n### Mocha\n\nUse [Mocha](http://visionmedia.github.com/mocha/)\n\nIf you are not using AMD, include `mocha-helper.js` from `tasks/mocha` after you include `mocha.js` and run `mocha.setup`. The helper will override `mocha.setup` if it detects PhantomJS.\n\nSee the example folder for a vanilla example.\n\nExample setup with AMD (advanced): https://gist.github.com/2655876\n\n### Maybe Growl?\n\nGrowl support is optional. I'm not sure what the Windows situation is with growl.\n\n### Hacks\n\nThe PhantomJS -> Grunt superdimensional conduit uses `alert`. If you have disabled or aliased alert in your app, this won't work. I have conveniently set a global `PHANTOMJS` on `window` so you can conditionally override alert in your app.\n\n## License\nCopyright (c) 2012 Kelly Miyashiro\nLicensed under the MIT license.", - "_id": "grunt-mocha@0.1.3", - "dist": { - "shasum": "6dce8fd5c361247d4ecb77017e124b6d7d865d8a" - }, + "readme": "Automatically run *client-side* mocha specs via grunt/mocha/PhantomJS\n\nFor a grunt task for server-side mocha tests, see https://github.com/yaymukund/grunt-simple-mocha\n\n# grunt-mocha\n\n(package/README format heavily borrowed from [grunt-jasmine-task](https://github.com/creynders/grunt-jasmine-task) and builtin QUnit task)\n\n[Grunt](https://github.com/cowboy/grunt) plugin for running Mocha browser specs in a headless browser (PhantomJS)\n\n## Getting Started\n\n### Task config\n\n```js\nmocha: {\n // runs all html files (except test2.html) in the test dir\n // In this example, there's only one, but you can add as many as\n // you want. You can split them up into different groups here\n // ex: admin: [ 'test/admin.html' ]\n all: [ 'test/**/!(test2).html' ],\n \n // Runs 'test/test2.html' with specified mocha options.\n // This variant auto-includes 'mocha-helper.js' so you do not have\n // to include it in your HTML spec file. Instead, you must add an\n // environment check before you run `mocha.run` in your HTML.\n test2: {\n\n // Test files\n src: [ 'test/test2.html' ],\n\n // mocha options\n options: {\n ignoreLeaks: false,\n grep: 'food'\n },\n\n // Indicates whether 'mocha.run()' should be executed in \n // 'mocha-helper.js'\n run: true\n }\n}\n```\n\n### Vanilla JS\n\n- Write mocha task description in grunt config using full format and specify `run: true` option (see `example/grunt.js` for details);\n- Check for PhantomJS `userAgent` in a test html file and run tests only in a real browser (see `example/test/test2.html` for details).\n\nIn this case you shouldn't include `mocha-helper.js` (it will be included automatically) and tests will be run from `mocha-helper.js`.\n\nAlternatively, include `mocha-helper.js` from `tasks/mocha` after you include `mocha.js` and run `mocha.setup` in your HTML file. The helper will override `mocha.setup` if it detects PhantomJS. See `example/test/test.html`.\n\n### AMD\n\nExample setup with AMD (advanced): https://gist.github.com/2655876\n\n### Grunt and this plugin\n\nFirst, make sure you have grunt installed globally, `npm install grunt -g`\n\nInstall this grunt plugin next to your project's [grunt.js gruntfile](https://github.com/cowboy/grunt/blob/master/docs/getting_started.md) with: `npm install grunt-mocha`\n\nThen add this line to your project's `grunt.js` gruntfile at the bottom:\n\n```javascript\ngrunt.loadNpmTasks('grunt-mocha');\n```\n\nAlso add this to the ```grunt.initConfig``` object in the same file:\n\n```javascript\nmocha: {\n index: ['specs/index.html']\n},\n```\n\nReplace ```specs/index.html``` with the location of your mocha spec running html file.\n\nNow you can run the mocha task with `grunt mocha`, but it won't work. That's because you need...\n\n### PhantomJS\n\nThis task is for running Mocha tests in a headless browser, PhantomJS. [See the FAQ on how to install PhantomJS](https://github.com/cowboy/grunt/blob/master/docs/faq.md#why-does-grunt-complain-that-phantomjs-isnt-installed).\n\n### Mocha\n\nUse [Mocha](http://visionmedia.github.com/mocha/)\n\n### Maybe Growl?\n\nGrowl support is optional. I'm not sure what the Windows situation is with growl.\n\n### Hacks\n\nThe PhantomJS -> Grunt superdimensional conduit uses `alert`. If you have disabled or aliased alert in your app, this won't work. I have conveniently set a global `PHANTOMJS` on `window` so you can conditionally override alert in your app.\n\n## License\nCopyright (c) 2012 Kelly Miyashiro\nLicensed under the MIT license.", + "readmeFilename": "README.md", + "_id": "grunt-mocha@0.1.7", "_from": "grunt-mocha" } diff --git a/node_modules/grunt-mocha/tasks/mocha.js b/node_modules/grunt-mocha/tasks/mocha.js index d96c7eb..d15c539 100644 --- a/node_modules/grunt-mocha/tasks/mocha.js +++ b/node_modules/grunt-mocha/tasks/mocha.js @@ -103,10 +103,11 @@ module.exports = function(grunt) { } }, done: function(failed, passed, total, duration) { + var nDuration = parseFloat(duration) || 0; status.failed += failed; status.passed += passed; status.total += total; - status.duration += duration; + status.duration += Math.round(nDuration*100)/100; // Print assertion errors here, if verbose mode is disabled. if (!option('verbose')) { if (failed > 0) { @@ -141,6 +142,16 @@ module.exports = function(grunt) { grunt.registerMultiTask('mocha', 'Run Mocha unit tests in a headless PhantomJS instance.', function() { // Get files as URLs. var urls = file.expandFileURLs(this.file.src); + // Get additional configuration + var config = {}; + + if (utils.kindOf(this.data) === 'object') { + config = utils._.clone(this.data); + delete config.src; + } + + var configStr = JSON.stringify(config); + verbose.writeln('Additional configuration: ' + configStr); // This task is asynchronous. var done = this.async(); @@ -184,10 +195,14 @@ module.exports = function(grunt) { var done = lines.slice(n).some(function(line) { // Get args and method. var args = JSON.parse(line); - var method = args.shift(); + var method = args[0]; // Execute method if it exists. if (phantomHandlers[method]) { + args.shift(); phantomHandlers[method].apply(null, args); + } else { + // Otherwise log read data + verbose.writeln("\n" + args.join(", ")); } // If the method name started with test, return true. Because the // Array#some method was used, this not only sets "done" to true, @@ -220,6 +235,8 @@ module.exports = function(grunt) { task.getFile('mocha/mocha-helper.js'), // URL to the Mocha .html test file to run. url, + // Additional configuration + configStr, // PhantomJS options. '--config=' + task.getFile('mocha/phantom.json') ], diff --git a/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js b/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js index 035c015..b8aae3f 100644 --- a/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js +++ b/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js @@ -1,6 +1,6 @@ /* * Is injected into the spec runner file - + * Copyright (c) 2012 Kelly Miyashiro * Copyright (c) 2012 "Cowboy" Ben Alman * Licensed under the MIT license. @@ -17,47 +17,80 @@ } var GruntReporter = function(runner){ - mocha.reporters.HTML.call(this, runner); + // 1.4.2 moved reporters to Mocha instead of mocha + var mochaInstance = window.Mocha || window.mocha; + + if (!mochaInstance) { + throw new Error('Mocha was not found, make sure you include Mocha in your HTML spec file.'); + } + + var reporters = mochaInstance.reporters; + + reporters.HTML.call(this, runner); + var stats = this.stats; - + runner.on('test', function(test) { sendMessage('testStart', test.title); }); - + runner.on('test end', function(test) { sendMessage('testDone', test.title, test.state); }); - + runner.on('suite', function(suite) { sendMessage('suiteStart', suite.title); }); - + runner.on('suite end', function(suite) { if (suite.root) return; sendMessage('suiteDone', suite.title); }); - + runner.on('fail', function(test, err) { sendMessage('testFail', test.title, err); }); - + runner.on('end', function() { var time = new Date() - stats.start; time = (time / 1000).toFixed(2); - + var failed = this.failures, passed = this.total - this.failures, total = this.total; - + sendMessage('done', failed, passed, total, time); }); }; - - if (window.PHANTOMJS) { - mocha.setup({ - ui: 'bdd', - ignoreLeaks: true, - reporter: GruntReporter - }); + + var phantom = window.PHANTOMJS; + if (phantom) { + // Default mocha options + var config = { + ui: 'bdd', + ignoreLeaks: true, + reporter: GruntReporter + }, + options = phantom.options, + key; + + if (options) { + // If options is a string, assume it is to set the UI (bdd/tdd etc) + if (typeof options === "string") { + config.ui = options; + } else { + // Extend defaults with passed options + for (key in options) { + config[key] = options[key]; + } + } + } + + config.reporter = GruntReporter; + + mocha.setup(config); + if (phantom.run) { + mocha.run(); + } } -}()); \ No newline at end of file +}()); diff --git a/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js b/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js index c89d628..1aac8ca 100644 --- a/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js +++ b/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js @@ -12,13 +12,16 @@ /*global phantom:true*/ var fs = require('fs'); +var system = require('system'); // The temporary file used for communications. -var tmpfile = phantom.args[0]; +var tmpfile = system.args[1]; // The Mocha helper file to be injected. -var mochaHelper = phantom.args[1]; +var mochaHelper = system.args[2]; // The Mocha .html test file to run. -var url = phantom.args[2]; +var url = system.args[3]; +// Config +var configStr = system.args[4]; // Keep track of the last time a Mocha message was sent. var last = new Date(); @@ -85,9 +88,9 @@ page.onResourceReceived = function(request) { }; page.onInitialized = function() { - page.evaluate(function() { - window.PHANTOMJS = true; - }); + page.evaluate(function(config) { + window.PHANTOMJS = config ? JSON.parse(config) : {}; + }, configStr); }; page.open(url, function(status) {